<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="author" content="https://github.com/JiHong88" />
    <meta name="keywords" content="wysiwyg,editor,javascript,suneditor,wysiwyg eidtor,rich text editor,html editor,contenteditable,위지위그 에디터 웹에디터">
    <meta name="description" content="Pure javascript wysiwyg web editor" />
    <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6933506635175446" crossorigin="anonymous"></script>
    <!-- Google tag (gtag.js) -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-W0R51STQTY"></script>
    <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    gtag('config', 'G-W0R51STQTY');
    </script>
    <title>SunEditor</title>
    <!-- sample css -->
    <link rel="stylesheet" href="../css/bootstrap.css" media="all">
    <link rel="stylesheet" href="../css/sample.css" media="all">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.8.2/css/all.min.css">
    <!-- suneditor -->
    <link href="../../dist/css/suneditor.min.css" rel="stylesheet">
    <style>
        .accordion {
            background-color: #ffebc1;
            color: #000;
            cursor: pointer;
            padding: 18px;
            width: 100%;
            border: none;
            text-align: left;
            outline: none;
            font-size: 15px;
            transition: 0.4s;
        }
        .accordion.active, .accordion:hover {
            background-color: #ffc449;
        }

        .panel {
            padding: 0;
            background-color: black;
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.2s ease-out;
        }

        .accordion:after {
            content: '\02795';
            font-size: 13px;
            color: #777;
            float: right;
            margin-left: 5px;
            }

        .accordion.active:after {
            content: "\2796";
        }

        /** custom class */
        .__se__format__range_custom {
            border: 5px solid #f4b124;
            background-color: #f4b12433;
            padding: 1rem !important;
            margin: 0 0 10px !important;
        }

        .se-custom-tag {
            background-color: #f4b124;
            color: #fff;
        }
    </style>
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" aria-expanded="false" onclick="buttonToggle()">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="../index.html" title="Suneditor"><b>SunEditor</b></a>
        </div>

        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="getting-started.html" title="Getting started">Getting started</a></li>
                <li><a href="examples.html" title="Examples">Examples</a></li>
                <li><a href="options.html" title="Options">Options</a></li>
                <li><a href="customPlugins.html" style="color:#fff;" title="CustomPlugins">CustomPlugins</a></li>
                <li><a href="document.html" title="Document">Document</a></li>
                <li class="badge">
                    <a href="https://www.paypal.me/jihong88?locale.x=en" target="_blank" title="PayPal Donate, Thanks"><img src="http://suneditor.com/docs/donate.png" class="donate-btn" alt="PayPal Donate" /></a>
                    <a href="https://github.com/JiHong88/SunEditor" target="_blank" title="Go to Github"><img alt="GitHub stars" src="https://img.shields.io/github/stars/jihong88/suneditor.svg?style=social"></a>
                </li>
            </ul>
        </div>
    </div>
</nav>

<div class="content">
    <article class="markdown-body entry-content">
        <!-- base -->
        <button class="accordion active">How to add a plugin ↓</button>
        <div class="panel" style="max-height: 1845px;">
<div class="highlight highlight-source-js"><pre>
<span class="pl-ent">/** You can use "dialog" and "component", "fileManager", "resizing" modules */</span>
<span class="pl-ent">/** An example of using the module can be seen in the 4.dialog sample. */</span>
<span class="pl-c">// import dialog from '/src/plugins/modules/[dialog, resizing]';</span>
<span class="pl-c">// &lt;script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/[dialog, resizing].js"&gt;&lt;/script&gt;</span>
<span class="pl-c">// SUNEDITOR_MODULES['dialog', 'resizing']</span>
<span class="pl-ent">/** ----------------------------------------------------------------------- */</span>

<span class="pl-ent">/** These are the free icon sites you can use */</span>
<span class="pl-c">// --svg</span>
<span class="pl-c">// https://icons8.com/</span>
<span class="pl-c">// https://icon-icons.com</span>
<span class="pl-c">// https://materialdesignicons.com</span>
<span class="pl-c">// https://material.io/resources/icons/?style=baseline</span>
<span class="pl-c">// https://www.freepik.com/</span>
<span class="pl-c">// --icon class</span>
<span class="pl-c">// https://fontawesome.com/, https://www.jsdelivr.com/package/npm/@fortawesome/fontawesome-free</span>
<span class="pl-c">// &lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.8.2/css/all.min.css"&gt;</span>
<span class="pl-ent">/** ----------------------------------------------------------------------- */</span>

<span class="pl-ent">// Define custom plugin</span>
<span class="pl-ent">// Common properties</span>
<span class="pl-k">var</span> <span class="pl-s1">customPlugin</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
    <span class="pl-k"><span class="pl-c">//</span> @Required @Unique</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'custom_example'</span><span class="pl-kos">,</span>
    <span class="pl-k"><span class="pl-c">//</span> @Required</span>
    <span class="pl-c1">display</span>: <span class="pl-kos">(</span><span class="pl-s">'container'</span> <span class="pl-c1">||</span> <span class="pl-s">'command'</span> <span class="pl-c1">||</span> <span class="pl-s">'submenu'</span> <span class="pl-c1">||</span> <span class="pl-s">'dialog'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    
    <span class="pl-k"><span class="pl-c">//</span> @options</span>
    <span class="pl-k"><span class="pl-c">//</span> * You can also set from the button list</span>
    <span class="pl-ent">// HTML title attribute (tooltip) - default: plugin's name</span>
    <span class="pl-c1">title</span>: <span class="pl-s">'Custom tooltip'</span>,
    <span class="pl-ent">// HTML to be append to button (icon)</span>
    <span class="pl-ent">// Recommend using the inline svg icon. - default: "&lt;span class="se-icon-text"&gt;!&lt;/span&gt;"</span>
    <span class="pl-c1">innerHTML</span>: <span class="pl-s">'&lt;svg /&gt;, &lt;i class="" /&gt;, &lt;span class="se-icon-text"&gt;C&lt;/span&gt;',</span>
    <span class="pl-ent">// The class of the button. - default: "se-btn"</span>
    <span class="pl-ent">// "se-code-view-enabled": It is not disable when on code view mode.</span>
    <span class="pl-ent">// "se-resizing-enabled": It is not disable when on using resizing module.</span>
    <span class="pl-c1">buttonClass</span>: <span class="pl-s">''</span>,

    <span class="pl-k"><span class="pl-c">//</span> @Required</span>
    <span class="pl-c1">add</span>: <span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">,</span> <span class="pl-s1">targetElement</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// How to set language when setting button properties of plugin directly in plugin</span>
        <span class="pl-k">const</span> <span class="pl-s1">titleList</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">en</span>: <span class="pl-s">'Custom'</span>,
            <span class="pl-c1">ko</span>: <span class="pl-s">'사용자 정의'</span>,
        <span class="pl-kos">}</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">title</span> <span class="pl-c1">=</span> <span class="pl-s1">titleList</span><span class="pl-kos">[</span><span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">.</span><span class="pl-en">code</span><span class="pl-kos">]</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    ...
<span class="pl-kos">}</span>

<span class="pl-c1">SUNEDITOR</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">'ex_custom'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-ent">// ------ When using CDN</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span><span class="pl-s1">customPlugin</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    
    <span class="pl-ent">// ------ When using node.js</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span><span class="pl-s1">custom_container</span><span class="pl-kos">,</span> <span class="pl-s1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">blockquote</span><span class="pl-kos">,</span> <span class="pl-s1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">link</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-ent">// --- all plguins</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">{</span>
        ...<span class="pl-s1">plugins</span><span class="pl-kos">,</span>
        custom_container
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    
    <span class="pl-ent">// ------ Add button list</span>
    <span class="pl-ent">// --- Add the name of the plugin to the button list.</span>
    <span class="pl-ent">// --- Button settings use the contents defined in the plugin.</span>
    <span class="pl-c1">buttonList</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[</span> <span class="pl-s">'custom_example'</span> <span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
    <span class="pl-ent">// --- You can set the button's properties directly.</span>
    <span class="pl-c1">buttonList</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[</span>
            <span class="pl-kos">{</span>
                <span class="pl-c">// plugin's name attribute</span>
                <span class="pl-c">// It must be the same as the name attribute of the plugin </span>
                <span class="pl-k">name</span>: <span class="pl-s">'custom_example'</span><span class="pl-kos">,</span> 
                <span class="pl-c">// Enter the "display" attribute value of your custom plugin.</span>
                <span class="pl-k">dataDisplay</span>: <span class="pl-kos">(</span><span class="pl-s">'container'</span> <span class="pl-c1">||</span> <span class="pl-s">'command'</span> <span class="pl-c1">||</span> <span class="pl-s">'submenu'</span> <span class="pl-c1">||</span> <span class="pl-s">'dialog'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
                
                <span class="pl-k"><span class="pl-c">//</span> @options</span>
                <span class="pl-c">// HTML title attribute</span>
                <span class="pl-c1">title</span>: <span class="pl-s">'Custom plugin'</span><span class="pl-kos">,</span> 
                <span class="pl-c">// button's class ("se-btn" class is registered, basic button click css is applied.)</span>
                <span class="pl-c1">buttonClass</span>:<span class="pl-s">''</span><span class="pl-kos">,</span> 
                <span class="pl-ent">// ------ HTML to be append to button</span>
                <span class="pl-ent">// --- Inline svg (The default size of the svg file is 16px.(suneditor.css:54L))</span>
                <span class="pl-c1">innerHTML</span>:<span class="pl-s">'&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="width:24px;height:24px;"&gt;&lt;path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/&gt;&lt;/svg&gt;'</span>
                <span class="pl-ent">// --- Icon class (This icon uses Font Awesome)</span>
                <span class="pl-c1">innerHTML</span>:<span class="pl-s">'&lt;i class="fas fa-font"&gt;&lt;/i&gt;'</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
        </div>


        <!-- container -->
        <a id="container" href="#container"><h4 class="sub-title">1. Plugins container</h4></a>
        <button class="accordion">sample ↓</button>
        <div class="panel" style="display: none;">
            <textarea id="ex_container" style="width: 1080px; height: 150px;"></textarea>
            <br>
<div class="highlight highlight-source-js"><pre><span class="pl-c">// ex) Adds a container of type "submenu" that contains a plugin.</span>
<span class="pl-k">var</span> <span class="pl-s1">custom_container</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
    <span class="pl-c">// <span class="pl-k">@Required @Unique</span></span>
    <span class="pl-c">// plugin name</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'custom_container'</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// data display</span>
    <span class="pl-c1">display</span>: <span class="pl-s">'container'</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// add function - It is called only once when the plugin is first run.</span>
    <span class="pl-c">// This function generates HTML to append and register the event.</span>
    <span class="pl-c">// arguments - (core : core object, targetElement : clicked button element)</span>
    <span class="pl-en">add</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">,</span> <span class="pl-s1">targetElement</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

        <span class="pl-c">// <span class="pl-k">@Required</span></span>
        <span class="pl-c">// Registering a namespace for caching as a plugin name in the context object</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">custom_container</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

        <span class="pl-c">// Generate submenu HTML</span>
        <span class="pl-c">// Always bind "core" when calling a plugin function</span>
        <span class="pl-k">let</span> <span class="pl-s1">listDiv</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setSubmenu</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// You must bind "core" object when registering an event.</span>
        <span class="pl-c">/** add event listeners */</span>
        <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'.se-form-group'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'click'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">onClick</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// <span class="pl-k">@Required</span></span>
        <span class="pl-c">// You must add the "submenu" element using the "core.initMenuTarget" method.</span>
        <span class="pl-c">/** append target button menu */</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-en">initMenuTarget</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">,</span> <span class="pl-s1">targetElement</span><span class="pl-kos">,</span> <span class="pl-s1">listDiv</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">setSubmenu</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-smi">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">listDiv</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'DIV'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">icons</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">icons</span><span class="pl-kos">;</span> <span class="pl-c">// assets/defaultIcons.js</span>
        <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-c1">className</span> <span class="pl-c1">=</span> <span class="pl-s">'se-menu-container se-submenu se-list-layer'</span><span class="pl-kos">;</span>
        <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-c1">innerHTML</span> <span class="pl-c1">=</span> <span class="pl-s">''</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;div class="se-list-inner"&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-form-group"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-c">// <span class="pl-k">@Required</span></span>
                    <span class="pl-c">// The "position" style of each element surrounding the button must be "relative".</span>
                    <span class="pl-c">// suneditor.css: .sun-editor .se-form-group &gt; div {position:relative;}</span>
                    <span class="pl-s">'&lt;div&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-c">// <span class="pl-k">@Required</span></span>
                        <span class="pl-c">// Enter the button name of the plug-in or default command in the button's "data-command"</span>
                        <span class="pl-s">'&lt;button type="button" class="se-btn se-tooltip" data-command="bold" style="margin: 0 !important;"&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">bold</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;span class="se-tooltip-text"&gt;Quote&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;button type="button" class="se-btn se-tooltip" data-command="blockquote"&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">blockquote</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;span class="se-tooltip-text"&gt;Quote&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;button type="button" class="se-btn se-tooltip" data-command="link"&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">link</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;span class="se-tooltip-text"&gt;Link&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;button type="button" class="se-btn se-tooltip" data-command="table"&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">table</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;span class="se-tooltip-text"&gt;Table&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;button type="button" class="se-btn se-tooltip" data-command="textStyle"&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">text_style</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;span class="se-tooltip-text"&gt;Text style&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;/div&gt;'</span><span class="pl-kos">;</span>

        <span class="pl-k">return</span> <span class="pl-s1">listDiv</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">onClick</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">preventDefault</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">stopPropagation</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">let</span> <span class="pl-s1">target</span> <span class="pl-c1">=</span> <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-c1">target</span><span class="pl-kos">;</span>
        <span class="pl-k">let</span> <span class="pl-s1">command</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>

        <span class="pl-k">while</span> <span class="pl-kos">(</span>!<span class="pl-s1">command</span> <span class="pl-c1">&amp;&amp;</span> !<span class="pl-pds">/<span class="pl-cce">^</span>UL<span class="pl-cce">$</span>/i</span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">target</span><span class="pl-kos">.</span><span class="pl-c1">tagName</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">command</span> <span class="pl-c1">=</span> <span class="pl-s1">target</span><span class="pl-kos">.</span><span class="pl-en">getAttribute</span><span class="pl-kos">(</span><span class="pl-s">'data-command'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">command</span><span class="pl-kos">)</span> <span class="pl-k">break</span><span class="pl-kos">;</span>
            <span class="pl-s1">target</span> <span class="pl-c1">=</span> <span class="pl-s1">target</span><span class="pl-kos">.</span><span class="pl-c1">parentNode</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">command</span><span class="pl-kos">)</span> <span class="pl-k">return</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">plugin</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">[</span><span class="pl-s1">command</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">actionCall</span><span class="pl-kos">(</span><span class="pl-s1">command</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">plugin</span> ? <span class="pl-s1">plugin</span><span class="pl-kos">.</span><span class="pl-c1">display</span> : <span class="pl-s">''</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s1">target</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c1">SUNEDITOR</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">'ex_container'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span><span class="pl-s1">custom_container</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">buttonList</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[</span>
            <span class="pl-kos">{</span>
                <span class="pl-k">name</span>: <span class="pl-s">'custom_container'</span><span class="pl-kos">,</span> 
                <span class="pl-k">dataDisplay</span>:<span class="pl-s">'container'</span><span class="pl-kos">,</span>
                <span class="pl-c1">title</span>:<span class="pl-s">'custom_container'</span><span class="pl-kos">,</span> 
                <span class="pl-c1">buttonClass</span>:<span class="pl-s">''</span><span class="pl-kos">,</span> 
                <span class="pl-c1">innerHTML</span>:<span class="pl-s">'&lt;svg viewBox="0 0 24 24" style="width:24px;height:24px;"&gt;&lt;path fill="currentColor" d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /&gt;&lt;/svg&gt;'</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
        </div>
        

        <!-- command -->
        <a id="command" href="#command"><h4 class="sub-title">2. Command</h4></a>
        <button class="accordion">sample ↓</button>
        <div class="panel" style="display: none;">
            <textarea id="ex_command" style="width: 1080px; height: 150px;"></textarea>
            <br>
<div class="highlight highlight-source-js"><pre><span class="pl-c">// ex) A command plugin to add "Range format element(util.isRangeFormatElement)" to selection</span>
<span class="pl-k">var</span> <span class="pl-s1">plugin_command</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
    <span class="pl-c">// <span class="pl-k">@Required @Unique</span></span>
    <span class="pl-c">// plugin name</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'customCommand'</span><span class="pl-kos">,</span>
    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// data display</span>
    <span class="pl-c1">display</span>: <span class="pl-s">'command'</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Options</span></span>
    <span class="pl-c1">title</span>: <span class="pl-s">'Add range tag'</span>, 
    <span class="pl-c1">buttonClass</span>: <span class="pl-s">''</span>, 
    <span class="pl-c1">innerHTML</span>: <span class="pl-s">'&lt;i class="fas fa-carrot"&gt;&lt;/i&gt;'</span>,

    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// add function - It is called only once when the plugin is first run.</span>
    <span class="pl-c">// This function generates HTML to append and register the event.</span>
    <span class="pl-c">// arguments - (core : core object, targetElement : clicked button element)</span>
    <span class="pl-en">add</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">,</span> <span class="pl-s1">targetElement</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">rangeTag</span> <span class="pl-c1">=</span> <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'div'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">addClass</span><span class="pl-kos">(</span><span class="pl-s1">rangeTag</span><span class="pl-kos">,</span> <span class="pl-s">'__se__format__range_custom'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// <span class="pl-k">@Required</span></span>
        <span class="pl-c">// Registering a namespace for caching as a plugin name in the context object</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">targetButton</span>: <span class="pl-s1">targetElement</span><span class="pl-kos">,</span>
            <span class="pl-c1">tag</span>: <span class="pl-s1">rangeTag</span>
        <span class="pl-kos">}</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Override core</span></span>
    <span class="pl-c">// Plugins with active methods load immediately when the editor loads.</span>
    <span class="pl-c">// Called each time the selection is moved.</span>
    <span class="pl-en">active</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">removeClass</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand</span><span class="pl-kos">.</span><span class="pl-c1">targetButton</span><span class="pl-kos">,</span> <span class="pl-s">'active'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">hasClass</span><span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-s">'__se__format__range_custom'</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">addClass</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand</span><span class="pl-kos">.</span><span class="pl-c1">targetButton</span><span class="pl-kos">,</span> <span class="pl-s">'active'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">return</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required, @Override core</span></span>
    <span class="pl-c">// The behavior of the "command plugin" must be defined in the "action" method.</span>
    <span class="pl-en">action</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">rangeTag</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getRangeFormatElement</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getSelectionNode</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">hasClass</span><span class="pl-kos">(</span><span class="pl-s1">rangeTag</span><span class="pl-kos">,</span> <span class="pl-s">'__se__format__range_custom'</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">detachRangeFormatElement</span><span class="pl-kos">(</span><span class="pl-s1">rangeTag</span><span class="pl-kos">,</span> null<span class="pl-kos">,</span> null<span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">applyRangeFormatElement</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand</span><span class="pl-kos">.</span><span class="pl-c1">tag</span><span class="pl-kos">.</span><span class="pl-en">cloneNode</span><span class="pl-kos">(</span><span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c">// ex) A command plugin to add "text node" to selection</span>
<span class="pl-k">var</span> <span class="pl-s1">plugin_command_2</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'customCommand_2'</span><span class="pl-kos">,</span>
    <span class="pl-c1">display</span>: <span class="pl-s">'command'</span><span class="pl-kos">,</span>

    <span class="pl-c1">title</span>:<span class="pl-s">'Text node change'</span><span class="pl-kos">,</span> 
    <span class="pl-c1">buttonClass</span>:<span class="pl-s">''</span><span class="pl-kos">,</span> 
    <span class="pl-c">// This icon uses Font Awesome</span>
    <span class="pl-c1">innerHTML</span>:<span class="pl-s">'&lt;i class="fas fa-font"&gt;&lt;/i&gt;'</span><span class="pl-kos">,</span> 

    <span class="pl-en">add</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">,</span> <span class="pl-s1">targetElement</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand_2</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">targetButton</span>: <span class="pl-s1">targetElement</span>
        <span class="pl-kos">}</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-en">active</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">removeClass</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand_2</span><span class="pl-kos">.</span><span class="pl-c1">targetButton</span><span class="pl-kos">,</span> <span class="pl-s">'active'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-pds">/<span class="pl-cce">^</span>mark<span class="pl-cce">$</span>/i</span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-c1">nodeName</span><span class="pl-kos">)</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">backgroundColor</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">addClass</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand_2</span><span class="pl-kos">.</span><span class="pl-c1">targetButton</span><span class="pl-kos">,</span> <span class="pl-s">'active'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">return</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-en">action</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">hasClass</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customCommand_2</span><span class="pl-kos">.</span><span class="pl-c1">targetButton</span><span class="pl-kos">,</span> <span class="pl-s">'active'</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">const</span> <span class="pl-s1">newNode</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'MARK'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-s1">newNode</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">backgroundColor</span> <span class="pl-c1">=</span> <span class="pl-s">'hsl(60,75%,60%)'</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">nodeChange</span><span class="pl-kos">(</span><span class="pl-s1">newNode</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">'background-color'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> null<span class="pl-kos">,</span> null<span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">nodeChange</span><span class="pl-kos">(</span>null<span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">'background-color'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">'mark'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c1">SUNEDITOR</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">'ex_command'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span><span class="pl-s1">plugin_command</span><span class="pl-kos">,</span> <span class="pl-s1">plugin_command_2</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">buttonList</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[</span clss="pl-s">'customCommand'<span></span>, <span class="pl-s">'customCommand_2'</span><span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
        </div>


        <!-- submenu -->
        <a id="submenu" href="#submenu"><h4 class="sub-title">3. Submenu</h4></a>
        <button class="accordion">sample ↓</button>
        <div class="panel" style="display: none;">
            <textarea id="ex_submenu" style="width: 1080px; height: 150px;"></textarea>
            <br>
<div class="highlight highlight-source-js"><pre><span class="pl-c">// ex) A submenu plugin that appends the contents of the input element to the editor</span>
<span class="pl-k">var</span> <span class="pl-s1">plugin_submenu</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
    <span class="pl-c">// <span class="pl-k">@Required @Unique</span></span>
    <span class="pl-c">// plugin name</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'custom_plugin_submenu'</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// data display</span>
    <span class="pl-c1">display</span>: <span class="pl-s">'submenu'</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Options</span></span>
    <span class="pl-c1">title</span>: <span class="pl-s">'Custom plugin of the submenu'</span>,
    <span class="pl-c1">buttonClass</span>: <span class="pl-s">''</span>, 
    <span class="pl-c1">innerHTML</span>: <span class="pl-s">'&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/&gt;&lt;/svg&gt;'</span>,

    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// add function - It is called only once when the plugin is first run.</span>
    <span class="pl-c">// This function generates HTML to append and register the event.</span>
    <span class="pl-c">// arguments - (core : core object, targetElement : clicked button element)</span>
    <span class="pl-en">add</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">,</span> <span class="pl-s1">targetElement</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

        <span class="pl-c">// <span class="pl-k">@Required</span></span>
        <span class="pl-c">// Registering a namespace for caching as a plugin name in the context object</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">targetButton</span>: <span class="pl-s1">targetElement</span><span class="pl-kos">,</span>
            <span class="pl-c1">textElement</span>: null<span class="pl-kos">,</span>
            <span class="pl-c1">currentSpan</span>: null
        <span class="pl-kos">}</span><span class="pl-kos">;</span>

        <span class="pl-c">// Generate submenu HTML</span>
        <span class="pl-c">// Always bind "core" when calling a plugin function</span>
        <span class="pl-k">let</span> <span class="pl-s1">listDiv</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setSubmenu</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// Input tag caching</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">textElement</span> <span class="pl-c1">=</span> <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'input'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// You must bind "core" object when registering an event.</span>
        <span class="pl-c">/** add event listeners */</span>
        <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'.se-btn-primary'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'click'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">onClick</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'.se-btn'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'click'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">onClickRemove</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// <span class="pl-k">@Required</span></span>
        <span class="pl-c">// You must add the "submenu" element using the "core.initMenuTarget" method.</span>
        <span class="pl-c">/** append target button menu */</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-en">initMenuTarget</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">,</span> <span class="pl-s1">targetElement</span><span class="pl-kos">,</span> <span class="pl-s1">listDiv</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">setSubmenu</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-smi">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">listDiv</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'DIV'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-c">// <span class="pl-k">@Required</span></span>
        <span class="pl-c">// A "se-submenu" class is required for the top level element.</span>
        <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-c1">className</span> <span class="pl-c1">=</span> <span class="pl-s">'se-menu-container se-submenu se-list-layer'</span><span class="pl-kos">;</span>
        <span class="pl-s1">listDiv</span><span class="pl-kos">.</span><span class="pl-c1">innerHTML</span> <span class="pl-c1">=</span> <span class="pl-s">''</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;div class="se-list-inner"&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;ul class="se-list-basic" style="width: 230px;"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;li&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;div class="se-form-group"&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;input class="se-input-form" type="text" placeholder="insert text" style="border: 1px solid #CCC;" /&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;button type="button" class="se-btn-primary se-tooltip"&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;strong&gt;OK&lt;/strong&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;'</span> <span class="pl-c1">+</span>
                                    <span class="pl-s">'&lt;span class="se-tooltip-text"&gt;Append span&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;button type="button" class="se-btn se-tooltip"&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;strong&gt;X&lt;/strong&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;'</span> <span class="pl-c1">+</span>
                                    <span class="pl-s">'&lt;span class="se-tooltip-text"&gt;Remove&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                                <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/li&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/ul&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;/div&gt;'</span><span class="pl-kos">;</span>

        <span class="pl-k">return</span> <span class="pl-s1">listDiv</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Override core</span></span>
    <span class="pl-c">// Plugins with active methods load immediately when the editor loads.</span>
    <span class="pl-c">// Called each time the selection is moved.</span>
    <span class="pl-en">active</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// If no tag matches, the "element" argument is called with a null value.</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">removeClass</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">targetButton</span><span class="pl-kos">,</span> <span class="pl-s">'active'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">textElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">currentSpan</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">hasClass</span><span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-s">'se-custom-tag'</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">addClass</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">targetButton</span><span class="pl-kos">,</span> <span class="pl-s">'active'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">textElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">currentSpan</span> <span class="pl-c1">=</span> <span class="pl-s1">element</span><span class="pl-kos">;</span>
            <span class="pl-k">return</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Override submenu</span></span>
    <span class="pl-c">// Called after the submenu has been rendered</span>
    <span class="pl-en">on</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">textElement</span><span class="pl-kos">.</span><span class="pl-en">focus</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">onClickRemove</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">span</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">currentSpan</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">span</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">removeItem</span><span class="pl-kos">(</span><span class="pl-s1">span</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">currentSpan</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>

            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">submenuOff</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">focus</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">onClick</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">value</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">textElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">.</span><span class="pl-en">trim</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">value</span><span class="pl-kos">)</span> <span class="pl-k">return</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">span</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">currentSpan</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">span</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">span</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span> <span class="pl-c1">=</span> <span class="pl-s1">value</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setRange</span><span class="pl-kos">(</span><span class="pl-s1">span</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-s1">span</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">functions</span><span class="pl-kos">.</span><span class="pl-en">insertHTML</span><span class="pl-kos">(</span><span class="pl-s">'&lt;span class="se-custom-tag"&gt;'</span> <span class="pl-smi">+</span> <span class="pl-c1">value</span> <span class="pl-smi">+</span> <span class="pl-s">'&lt;/span&gt;'</span>, <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customSubmenu</span><span class="pl-kos">.</span><span class="pl-c1">textElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">submenuOff</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c1">SUNEDITOR</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">'ex_submenu'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span><span class="pl-s1">plugin_submenu</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">buttonList</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[</span><span class="pl-s">'custom_plugin_submenu'</span><span class="pl-kos">,</span><span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
        </div>


        <!-- dialog -->
        <a id="dialog" href="#dialog"><h4 class="sub-title">4. Dialog</h4></a>
        <button class="accordion">sample ↓</button>
        <div class="panel" style="display: none;">
            <textarea id="ex_dialog" style="width: 1080px; height: 150px;"></textarea>
            <br>
<div class="highlight highlight-source-js"><pre><span class="pl-c">// Import "dialog" module</span>
<span class="pl-c">// import dialog from '../../src/plugins/modules/dialog';</span>
<span class="pl-c1">&lt;</span><span class="pl-ent">script</span> <span class="pl-c1">src</span><span class="pl-c1">=</span><span class="pl-s">"https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/dialog.js"</span><span class="pl-c1">&gt;</span><span class="pl-c1">&lt;</span>/<span class="pl-ent">script</span><span class="pl-c1">&gt;</span>

<span class="pl-c">// ex) ex) A link dialog plugin with multiple target options.</span>
<span class="pl-k">var</span> <span class="pl-s1">plugin_dialog</span><span class="pl-kos"> = </span><span class="pl-kos">{</span>
    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// plugin name</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'customLink'</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// data display</span>
    <span class="pl-c1">display</span>: <span class="pl-s">'dialog'</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required</span></span>
    <span class="pl-c">// add function - It is called only once when the plugin is first run.</span>
    <span class="pl-c">// This function generates HTML to append and register the event.</span>
    <span class="pl-c">// arguments - (core : core object, targetElement : clicked button element)</span>
    <span class="pl-en">add</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

        <span class="pl-c">// If you are using a module, you must register the module using the "addModule" method.</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-en">addModule</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-c1">SUNEDITOR_MODULES</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// <span class="pl-k">@Required</span></span>
        <span class="pl-c">// Registering a namespace for caching as a plugin name in the context object</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">focusElement</span>: null<span class="pl-kos">,</span> <span class="pl-c">// <span class="pl-k">@Override</span> // This element has focus when the dialog is opened.</span>
            <span class="pl-c1">targetSelect</span>: null<span class="pl-kos">,</span>
            <span class="pl-c1">linkAnchorText</span>: null<span class="pl-kos">,</span>
            <span class="pl-c1">_linkAnchor</span>: null
        <span class="pl-kos">}</span><span class="pl-kos">;</span>

        <span class="pl-c">/** link dialog */</span>
        <span class="pl-k">let</span> <span class="pl-s1">link_dialog</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setDialog</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">modal</span> <span class="pl-c1">=</span> <span class="pl-s1">link_dialog</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span> <span class="pl-c1">=</span> <span class="pl-s1">link_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'._se_link_url'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">linkAnchorText</span> <span class="pl-c1">=</span> <span class="pl-s1">link_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'._se_link_text'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">targetSelect</span> <span class="pl-c1">=</span> <span class="pl-s1">link_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'.se-input-select'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/** link controller */</span>
        <span class="pl-k">let</span> <span class="pl-s1">link_controller</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setController_LinkButton</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">linkController</span> <span class="pl-c1">=</span> <span class="pl-s1">link_controller</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>

        <span class="pl-c">/** add event listeners */</span>
        <span class="pl-s1">link_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'form'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'submit'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">submit</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">link_controller</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'click'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">onClick_linkController</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/** append html */</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">modal</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">link_dialog</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/** append controller */</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">relative</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">link_controller</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/** empty memory */</span>
        <span class="pl-s1">link_dialog</span> <span class="pl-c1">=</span> null<span class="pl-kos">,</span> <span class="pl-s1">link_controller</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/** dialog */</span>
    <span class="pl-en">setDialog</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-smi">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">lang</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">dialog</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'DIV'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">targetList</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span>
            <span class="pl-kos">{</span> <span class="pl-c1">target</span>: <span class="pl-s">'_blank'</span><span class="pl-kos">,</span> <span class="pl-c1">name</span>: <span class="pl-s">'New window'</span><span class="pl-kos">}</span><span class="pl-kos">,</span>
            <span class="pl-kos">{</span> <span class="pl-c1">target</span>: <span class="pl-s">'_parent'</span><span class="pl-kos">,</span> <span class="pl-c1">name</span>: <span class="pl-s">'Parent frame'</span><span class="pl-kos">}</span><span class="pl-kos">,</span>
            <span class="pl-kos">{</span> <span class="pl-c1">target</span>: <span class="pl-s">'_top'</span><span class="pl-kos">,</span> <span class="pl-c1">name</span>: <span class="pl-s">'First frame'</span><span class="pl-kos">,</span> <span class="pl-c1">selected</span>: <span class="pl-c1">true</span><span class="pl-kos">}</span><span class="pl-kos">,</span>
            <span class="pl-kos">{</span> <span class="pl-c1">target</span>: <span class="pl-s">'AnyFrame'</span><span class="pl-kos">,</span> <span class="pl-c1">name</span>: <span class="pl-s">'Frame name'</span><span class="pl-kos">}</span><span class="pl-kos">,</span>
            <span class="pl-kos">{</span> <span class="pl-c1">target</span>: <span class="pl-s">'_dialog'</span><span class="pl-kos">,</span> <span class="pl-c1">name</span>: <span class="pl-s">'Self defined dialog'</span><span class="pl-kos">}</span>
        <span class="pl-kos">]</span><span class="pl-kos">;</span>

        <span class="pl-s1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">className</span> <span class="pl-c1">=</span> <span class="pl-s">'se-dialog-content'</span><span class="pl-kos">;</span>
        <span class="pl-s1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">display</span> <span class="pl-c1">=</span> <span class="pl-s">'none'</span><span class="pl-kos">;</span>
        <span class="pl-k">let</span> <span class="pl-s1">html</span> <span class="pl-c1">=</span> <span class="pl-s">''</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;form class="editor_link"&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-dialog-header"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="button" data-command="close" class="se-btn se-dialog-close" aria-label="Close" title="'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">close</span> <span class="pl-c1">+</span> <span class="pl-s">'"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">icons</span><span class="pl-kos">.</span><span class="pl-c1">cancel</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;span class="se-modal-title"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">linkBox</span><span class="pl-kos">.</span><span class="pl-c1">title</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-dialog-body"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div class="se-dialog-form"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;label&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">linkBox</span><span class="pl-kos">.</span><span class="pl-c1">url</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/label&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;input class="se-input-form _se_link_url" type="text" /&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div class="se-dialog-form"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;label&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">linkBox</span><span class="pl-kos">.</span><span class="pl-c1">text</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/label&gt;&lt;input class="se-input-form _se_link_text" type="text" /&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div class="se-dialog-form se-dialog-form-footer"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;select class="se-input-select" title="links"&gt;'</span><span class="pl-kos">;</span>
                            <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">len</span> <span class="pl-c1">=</span> <span class="pl-s1">targetList</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">,</span> <span class="pl-s1">t</span><span class="pl-kos">,</span> <span class="pl-s1">selected</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">len</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                                <span class="pl-s1">t</span> <span class="pl-c1">=</span> <span class="pl-s1">targetList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
                                <span class="pl-s1">selected</span> <span class="pl-c1">=</span> <span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-c1">selected</span> ? <span class="pl-s">' selected'</span> : <span class="pl-s">''</span><span class="pl-kos">;</span>
                                <span class="pl-s1">html</span> <span class="pl-c1">+=</span> <span class="pl-s">'&lt;option value="'</span> <span class="pl-c1">+</span> <span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-c1">target</span> <span class="pl-c1">+</span> <span class="pl-s">'"'</span> <span class="pl-c1">+</span> <span class="pl-s1">selected</span> <span class="pl-c1">+</span> <span class="pl-s">'&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/option&gt;'</span><span class="pl-kos">;</span>
                            <span class="pl-kos">}</span>
                        <span class="pl-s1">html</span> <span class="pl-c1">+=</span> <span class="pl-s">'&lt;/select&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-dialog-footer"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="submit" class="se-btn-primary" title="'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">submitButton</span> <span class="pl-c1">+</span> <span class="pl-s">'"&gt;&lt;span&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">submitButton</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;/form&gt;'</span><span class="pl-kos">;</span>


        <span class="pl-s1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">innerHTML</span> <span class="pl-c1">=</span> <span class="pl-s1">html</span><span class="pl-kos">;</span>

        <span class="pl-k">return</span> <span class="pl-s1">dialog</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/** modify controller button */</span>
    <span class="pl-en">setController_LinkButton</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-smi">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">lang</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">icons</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">icons</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">link_btn</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'DIV'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-s1">link_btn</span><span class="pl-kos">.</span><span class="pl-c1">className</span> <span class="pl-c1">=</span> <span class="pl-s">'se-controller se-controller-link'</span><span class="pl-kos">;</span>
        <span class="pl-s1">link_btn</span><span class="pl-kos">.</span><span class="pl-c1">innerHTML</span> <span class="pl-c1">=</span> <span class="pl-s">''</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;div class="se-arrow se-arrow-up"&gt;&lt;/div&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;div class="link-content"&gt;&lt;span&gt;&lt;a target="_blank" href=""&gt;&lt;/a&gt;&amp;nbsp;&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-btn-group"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="button" data-command="update" tabindex="-1" class="se-tooltip"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">edit</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;&lt;span class="se-tooltip-text"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">.</span><span class="pl-c1">edit</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="button" data-command="unlink" tabindex="-1" class="se-tooltip"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">unlink</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;&lt;span class="se-tooltip-text"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">.</span><span class="pl-c1">unlink</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="button" data-command="delete" tabindex="-1" class="se-tooltip"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">delete</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;&lt;span class="se-tooltip-text"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">.</span><span class="pl-c1">remove</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;/div&gt;'</span><span class="pl-kos">;</span>

        <span class="pl-k">return</span> <span class="pl-s1">link_btn</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required, @Override dialog</span></span>
    <span class="pl-c">// This method is called when the plugin button is clicked.</span>
    <span class="pl-c">// Open the modal window here.</span>
    <span class="pl-en">open</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// open.call(core, pluginName, isModify)</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">open</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customLink'</span><span class="pl-kos">,</span> <span class="pl-s">'customLink'</span> <span class="pl-c1">===</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">currentControllerName</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">submit</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">showLoading</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">preventDefault</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">stopPropagation</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">submitAction</span> <span class="pl-c1">=</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">.</span><span class="pl-en">trim</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>

            <span class="pl-k">const</span> <span class="pl-s1">contextLink</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">url</span> <span class="pl-c1">=</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">anchor</span> <span class="pl-c1">=</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">linkAnchorText</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">anchorText</span> <span class="pl-c1">=</span> <span class="pl-s1">anchor</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span> ? <span class="pl-s1">url</span> : <span class="pl-s1">anchor</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">;</span>

            <span class="pl-c">// When opened for modification "this.context.dialog.updateModal" is true</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">updateModal</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-k">const</span> <span class="pl-s1">oA</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'A'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                <span class="pl-s1">oA</span><span class="pl-kos">.</span><span class="pl-c1">href</span> <span class="pl-c1">=</span> <span class="pl-s1">url</span><span class="pl-kos">;</span>
                <span class="pl-s1">oA</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span> <span class="pl-c1">=</span> <span class="pl-s1">anchorText</span><span class="pl-kos">;</span>
                <span class="pl-s1">oA</span><span class="pl-kos">.</span><span class="pl-c1">target</span> <span class="pl-c1">=</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">targetSelect</span><span class="pl-kos">.</span><span class="pl-c1">selectedOptions</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">;</span>

                <span class="pl-k">const</span> <span class="pl-s1">selectedFormats</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getSelectedElements</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">selectedFormats</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">1</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                    <span class="pl-k">const</span> <span class="pl-s1">oFormat</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s1">selectedFormats</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">nodeName</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                    <span class="pl-s1">oFormat</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">oA</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">insertNode</span><span class="pl-kos">(</span><span class="pl-s1">oFormat</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
                    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">insertNode</span><span class="pl-kos">(</span><span class="pl-s1">oA</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                <span class="pl-kos">}</span>

                <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setRange</span><span class="pl-kos">(</span><span class="pl-s1">oA</span><span class="pl-kos">.</span><span class="pl-c1">childNodes</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">oA</span><span class="pl-kos">.</span><span class="pl-c1">childNodes</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-s1">oA</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
                <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">href</span> <span class="pl-c1">=</span> <span class="pl-s1">url</span><span class="pl-kos">;</span>
                <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span> <span class="pl-c1">=</span> <span class="pl-s1">anchorText</span><span class="pl-kos">;</span>
                <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">target</span> <span class="pl-c1">=</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">targetSelect</span><span class="pl-kos">.</span><span class="pl-c1">selectedOptions</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">;</span>

                <span class="pl-c">// set range</span>
                <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setRange</span><span class="pl-kos">(</span><span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">childNodes</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">childNodes</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>

            <span class="pl-c">// history stack</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">history</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

            <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
            <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">linkAnchorText</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">try</span> <span class="pl-kos">{</span>
            <span class="pl-s1">submitAction</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">finally</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">close</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">closeLoading</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">focus</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Override core</span></span>
    <span class="pl-c">// Plugins with active methods load immediately when the editor loads.</span>
    <span class="pl-c">// Called each time the selection is moved.</span>
    <span class="pl-en">active</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">controllerArray</span><span class="pl-kos">.</span><span class="pl-en">indexOf</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">linkController</span><span class="pl-kos">)</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">-</span><span class="pl-c1">1</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">controllersOff</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">isAnchor</span><span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-en">getAttribute</span><span class="pl-kos">(</span><span class="pl-s">'data-image-link'</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> null<span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">controllerArray</span><span class="pl-kos">.</span><span class="pl-en">indexOf</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">linkController</span><span class="pl-kos">)</span> <span class="pl-c1">&lt;</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">call_controller</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">element</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
            <span class="pl-k">return</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Override dialog</span></span>
    <span class="pl-c">// This method is called just before the dialog opens.</span>
    <span class="pl-c">// If "update" argument is true, it is not a new call, but a call to modify an already created element.</span>
    <span class="pl-en">on</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">update</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">update</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">init</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">linkAnchorText</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getSelection</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toString</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-c">// "update" and "this.context.dialog.updateModal" are always the same value.</span>
            <span class="pl-c">// This code is an exception to the "link" plugin.</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">updateModal</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">href</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">linkAnchorText</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">targetSelect</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">target</span> <span class="pl-c1">||</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">call_controller</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">selectionATag</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">editLink</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span> <span class="pl-c1">=</span> <span class="pl-s1">selectionATag</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">linkBtn</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">linkController</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">link</span> <span class="pl-c1">=</span> <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'a'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">href</span> <span class="pl-c1">=</span> <span class="pl-s1">selectionATag</span><span class="pl-kos">.</span><span class="pl-c1">href</span><span class="pl-kos">;</span>
        <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">title</span> <span class="pl-c1">=</span> <span class="pl-s1">selectionATag</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">;</span>
        <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span> <span class="pl-c1">=</span> <span class="pl-s1">selectionATag</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">offset</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getOffset</span><span class="pl-kos">(</span><span class="pl-s1">selectionATag</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">wysiwygFrame</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">top</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">offset</span><span class="pl-kos">.</span><span class="pl-c1">top</span> <span class="pl-c1">+</span> <span class="pl-s1">selectionATag</span><span class="pl-kos">.</span><span class="pl-c1">offsetHeight</span> <span class="pl-c1">+</span> <span class="pl-c1">10</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>
        <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">offset</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">-</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">wysiwygFrame</span><span class="pl-kos">.</span><span class="pl-c1">scrollLeft</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>

        <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">display</span> <span class="pl-c1">=</span> <span class="pl-s">'block'</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">overLeft</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">wysiwygFrame</span><span class="pl-kos">.</span><span class="pl-c1">offsetWidth</span> <span class="pl-c1">-</span> <span class="pl-kos">(</span><span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">offsetLeft</span> <span class="pl-c1">+</span> <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">offsetWidth</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">overLeft</span> <span class="pl-c1">&lt;</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">offsetLeft</span> <span class="pl-c1">+</span> <span class="pl-s1">overLeft</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>
            <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">firstElementChild</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-c1">20</span> <span class="pl-c1">-</span> <span class="pl-s1">overLeft</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-s1">linkBtn</span><span class="pl-kos">.</span><span class="pl-c1">firstElementChild</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-s">'20px'</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
        
        <span class="pl-c">// Show controller at editor area (controller elements, function, "controller target element(@Required)", "controller name(@Required)", etc..)</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">controllersOn</span><span class="pl-kos">(</span><span class="pl-s1">linkBtn</span><span class="pl-kos">,</span> <span class="pl-s1">selectionATag</span><span class="pl-kos">,</span> <span class="pl-s">'customLink'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">onClick_linkController</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">stopPropagation</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">command</span> <span class="pl-c1">=</span> <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-c1">target</span><span class="pl-kos">.</span><span class="pl-en">getAttribute</span><span class="pl-kos">(</span><span class="pl-s">'data-command'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">command</span><span class="pl-kos">)</span> <span class="pl-k">return</span><span class="pl-kos">;</span>

        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">preventDefault</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-pds">/update/</span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">command</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">const</span> <span class="pl-s1">contextLink</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">;</span>
            <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">href</span><span class="pl-kos">;</span>
            <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">linkAnchorText</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">;</span>
            <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">targetSelect</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">targetSelect</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">open</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customLink'</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
        <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-pds">/unlink/</span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">command</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">const</span> <span class="pl-s1">sc</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getChildElement</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">,</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">current</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-k">return</span> <span class="pl-s1">current</span><span class="pl-kos">.</span><span class="pl-c1">childNodes</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span> <span class="pl-c1">||</span> <span class="pl-s1">current</span><span class="pl-kos">.</span><span class="pl-c1">nodeType</span> <span class="pl-c1">===</span> <span class="pl-c1">3</span><span class="pl-kos">;</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">ec</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getChildElement</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">,</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">current</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-k">return</span> <span class="pl-s1">current</span><span class="pl-kos">.</span><span class="pl-c1">childNodes</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span> <span class="pl-c1">||</span> <span class="pl-s1">current</span><span class="pl-kos">.</span><span class="pl-c1">nodeType</span> <span class="pl-c1">===</span> <span class="pl-c1">3</span><span class="pl-kos">;</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setRange</span><span class="pl-kos">(</span><span class="pl-s1">sc</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">ec</span><span class="pl-kos">,</span> <span class="pl-s1">ec</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">nodeChange</span><span class="pl-kos">(</span>null<span class="pl-kos">,</span> null<span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">'A'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
        <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-c">/** delete */</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">removeItem</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">focus</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

            <span class="pl-c">// history stack</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">history</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">controllersOff</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// <span class="pl-k">@Required, @Override dialog</span></span>
    <span class="pl-c">// This method is called when the dialog window is closed.</span>
    <span class="pl-c">// Initialize the properties.</span>
    <span class="pl-en">init</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">contextLink</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customLink</span><span class="pl-kos">;</span>
        <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">linkController</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">display</span> <span class="pl-c1">=</span> <span class="pl-s">'none'</span><span class="pl-kos">;</span>
        <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">_linkAnchor</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>
        <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">linkAnchorText</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-s1">contextLink</span><span class="pl-kos">.</span><span class="pl-c1">targetSelect</span><span class="pl-kos">.</span><span class="pl-c1">selectedIndex</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c1">SUNEDITOR</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">'ex_dialog'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span><span class="pl-s1">plugin_dialog</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">buttonList</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[</span>
            <span class="pl-kos">{</span>
                <span class="pl-k">name</span>: <span class="pl-s">'customLink'</span><span class="pl-kos">,</span> 
                <span class="pl-k">dataDisplay</span>:<span class="pl-s">'dialog'</span><span class="pl-kos">,</span>
                <span class="pl-c1">title</span>:<span class="pl-s">'Custom link'</span><span class="pl-kos">,</span> 
                <span class="pl-c1">buttonClass</span>:<span class="pl-s">''</span><span class="pl-kos">,</span> 
                <span class="pl-c1">innerHTML</span>:<span class="pl-s">'&lt;svg viewBox="0 0 24 24"&gt;&lt;path d="M10.59,13.41C11,13.8 11,14.44 10.59,14.83C10.2,15.22 9.56,15.22 9.17,14.83C7.22,12.88 7.22,9.71 9.17,7.76V7.76L12.71,4.22C14.66,2.27 17.83,2.27 19.78,4.22C21.73,6.17 21.73,9.34 19.78,11.29L18.29,12.78C18.3,11.96 18.17,11.14 17.89,10.36L18.36,9.88C19.54,8.71 19.54,6.81 18.36,5.64C17.19,4.46 15.29,4.46 14.12,5.64L10.59,9.17C9.41,10.34 9.41,12.24 10.59,13.41M13.41,9.17C13.8,8.78 14.44,8.78 14.83,9.17C16.78,11.12 16.78,14.29 14.83,16.24V16.24L11.29,19.78C9.34,21.73 6.17,21.73 4.22,19.78C2.27,17.83 2.27,14.66 4.22,12.71L5.71,11.22C5.7,12.04 5.83,12.86 6.11,13.65L5.64,14.12C4.46,15.29 4.46,17.19 5.64,18.36C6.81,19.54 8.71,19.54 9.88,18.36L13.41,14.83C14.59,13.66 14.59,11.76 13.41,10.59C13,10.2 13,9.56 13.41,9.17Z" /&gt;&lt;/svg&gt;'</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">]</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
        </div>

        <!-- dialog & component & fileManager-->
        <a id="dialog_component_filemanager" href="#dialog_component_filemanager"><h4 class="sub-title">5. Dialog & component & fileManager</h4></a>
        <button class="accordion">sample ↓</button>
        <div class="panel" style="display: none;">
            <textarea id="ex_dialog_component_fileManager" style="width: 1080px; height: 150px;"></textarea>
            <div class="component-list">
                <div class="file-list-info">
                    <span>Audio list</span>
                </div>
                <div class="component-file-list">
                    <ul id="audio_list">
                    </ul>
                </div>
            </div>
            <br>
<div class="highlight highlight-text-html-basic"><pre><span class="pl-kos">&lt;</span><span class="pl-ent">script</span> <span class="pl-c1">src</span>="<span class="pl-s">https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/dialog.js</span>"<span class="pl-kos">&gt;</span><span class="pl-kos">&lt;/</span><span class="pl-ent">script</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;</span><span class="pl-ent">script</span> <span class="pl-c1">src</span>="<span class="pl-s">https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/component.js</span>"<span class="pl-kos">&gt;</span><span class="pl-kos">&lt;/</span><span class="pl-ent">script</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;</span><span class="pl-ent">script</span> <span class="pl-c1">src</span>="<span class="pl-s">https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/fileManager.js</span>"<span class="pl-kos">&gt;</span><span class="pl-kos">&lt;/</span><span class="pl-ent">script</span><span class="pl-kos">&gt;</span>
<span class="pl-c">&lt;!-- &lt;script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/resizing.js"&gt;&lt;/script&gt; --&gt;</span>

<span class="pl-kos">&lt;</span><span class="pl-ent">div</span> <span class="pl-c1">class</span>="<span class="pl-s">component-list</span>"<span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">div</span> <span class="pl-c1">class</span>="<span class="pl-s">file-list-info</span>"<span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">span</span><span class="pl-kos">&gt;</span>Audio list<span class="pl-kos">&lt;/</span><span class="pl-ent">span</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;/</span><span class="pl-ent">div</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">div</span> <span class="pl-c1">class</span>="<span class="pl-s">component-file-list</span>"<span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">ul</span> <span class="pl-c1">id</span>="<span class="pl-s">audio_list</span>"<span class="pl-kos">&gt;</span><span class="pl-kos">&lt;/</span><span class="pl-ent">ul</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;/</span><span class="pl-ent">div</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;/</span><span class="pl-ent">div</span><span class="pl-kos">&gt;</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c">/** import modules when using nodejs */</span>
<span class="pl-c">// import dialog from 'suneditor/src/plugins/modules/dialog';</span>
<span class="pl-c">// import component from 'suneditor/src/plugins/modules/component';</span>
<span class="pl-c">// import fileManager from 'suneditor/src/plugins/modules/fileManager';</span>
<span class="pl-c">// import resizing from 'suneditor/src/plugins/modules/resizing';</span>
<span class="pl-c">// import { dialog, component, fileManager, resizing } from 'suneditor/src/plugins/modules';</span>

<span class="pl-c">/** audio list */</span>
<span class="pl-k">const</span> <span class="pl-s1">audioTable</span> <span class="pl-c1">=</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">'audio_list'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> <span class="pl-s1">audioList</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">;</span>

<span class="pl-k">function</span> <span class="pl-en" style="color: #20ac40;">userFunc_audioUpload</span> <span class="pl-kos">(</span><span class="pl-s1">targetElement</span><span class="pl-kos">,</span> <span class="pl-s1">index</span><span class="pl-kos">,</span> <span class="pl-s1">state</span><span class="pl-kos">,</span> <span class="pl-s1">info</span><span class="pl-kos">,</span> <span class="pl-s1">remainingFilesCount</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'audioInfo'</span><span class="pl-kos">,</span> <span class="pl-s1">info</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">state</span> <span class="pl-c1">===</span> <span class="pl-s">'delete'</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">audioList</span><span class="pl-kos">.</span><span class="pl-en">splice</span><span class="pl-kos">(</span><span class="pl-en">findIndex</span><span class="pl-kos">(</span><span class="pl-s1">audioList</span><span class="pl-kos">,</span> <span class="pl-s1">index</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">state</span> <span class="pl-c1">===</span> <span class="pl-s">'create'</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">audioList</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s1">info</span><span class="pl-kos">)</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span> <span class="pl-c">// update</span>
            <span class="pl-c">//</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>

    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">remainingFilesCount</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'audioList'</span><span class="pl-kos">,</span> <span class="pl-s1">audioList</span><span class="pl-kos">)</span>
        <span class="pl-en">_setAudioList</span><span class="pl-kos">(</span><span class="pl-s1">audioList</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-en">_setAudioList</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">list</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>

    <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">info</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">audioList</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-s1">audioList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
            
        <span class="pl-s1">list</span> <span class="pl-c1">+=</span> <span class="pl-s">'&lt;li&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button title="delete" onclick="_selectAudio(\'delete\','</span> <span class="pl-c1">+</span> <span class="pl-s1">info</span><span class="pl-kos">.</span><span class="pl-c1">index</span> <span class="pl-c1">+</span> <span class="pl-s">')"&gt;X&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;a href="javascript:void(0)" onclick="_selectAudio(\'select\','</span> <span class="pl-c1">+</span> <span class="pl-s1">info</span><span class="pl-kos">.</span><span class="pl-c1">index</span> <span class="pl-c1">+</span> <span class="pl-s">')"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">info</span><span class="pl-kos">.</span><span class="pl-c1">src</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/a&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/li&gt;'</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-s1">audioTable</span><span class="pl-kos">.</span><span class="pl-c1">innerHTML</span> <span class="pl-c1">=</span> <span class="pl-s1">list</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-en">_selectAudio</span> <span class="pl-kos">(</span><span class="pl-s1">type</span><span class="pl-kos">,</span> <span class="pl-s1">index</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">audioList</span><span class="pl-kos">[</span><span class="pl-en">findIndex</span><span class="pl-kos">(</span><span class="pl-s1">audioList</span><span class="pl-kos">,</span> <span class="pl-s1">index</span><span class="pl-kos">)</span><span class="pl-kos">]</span><span class="pl-kos">[</span><span class="pl-s1">type</span><span class="pl-kos">]</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c">// ex) A link dialog plugin with used [dialog, component, fileManager] module</span>
<span class="pl-c">// Sample audio : https://file-examples.com/index.php/sample-audio-files/</span>
<span class="pl-k">var</span> <span class="pl-kos">plugin_dialog_component_fileManager</span><span class="pl-kos"> = </span><span class="pl-kos">{</span>
    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span> <span class="pl-k">@Unique</span></span>
<span class="pl-c">     * plugin name</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">name</span>: <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span></span>
<span class="pl-c">     * data display</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">display</span>: <span class="pl-s">'dialog'</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@options</span></span>
<span class="pl-c">     * You can also set from the button list</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">title</span>:<span class="pl-s">'Custom audio'</span><span class="pl-kos">,</span> 
    <span class="pl-c1">buttonClass</span>:<span class="pl-s">''</span><span class="pl-kos">,</span> 
    <span class="pl-c1">innerHTML</span>:<span class="pl-s">'&lt;span class="se-icon-text"&gt;?&lt;/span&gt;'</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span></span>
<span class="pl-c">     * add function - It is called only once when the plugin is first run.</span>
<span class="pl-c">     * This function generates HTML to append and register the event.</span>
<span class="pl-c">     * arguments - (core : core object, targetElement : clicked button element)</span>
<span class="pl-c">     */</span>
    <span class="pl-en">add</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

        <span class="pl-c">// If you are using a module, you must register the module using the "addModule" method.</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-en">addModule</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-s1">dialog</span><span class="pl-kos">,</span> <span class="pl-s1">component</span><span class="pl-kos">,</span> <span class="pl-s1">fileManager</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/**</span>
<span class="pl-c">         * <span class="pl-k">@Required</span></span>
<span class="pl-c">         * Registering a namespace for caching as a plugin name in the context object</span>
<span class="pl-c">         */</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">_infoList</span>: <span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c">// <span class="pl-k">@Override</span> fileManager</span>
            <span class="pl-c1">_infoIndex</span>: <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c">// <span class="pl-k">@Override</span> fileManager</span>
            <span class="pl-c1">_uploadFileLength</span>: <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c">// <span class="pl-k">@Override</span> fileManager</span>
            <span class="pl-c1">focusElement</span>: null<span class="pl-kos">,</span> <span class="pl-c">// <span class="pl-k">@Override</span> // This element has focus when the dialog is opened.</span>
            <span class="pl-c1">targetSelect</span>: null<span class="pl-kos">,</span>
            <span class="pl-c">// <span class="pl-k">@require</span> <span class="pl-k">@Override</span> component</span>
            <span class="pl-c1">_element</span>: null<span class="pl-kos">,</span>
            <span class="pl-c1">_cover</span>: null<span class="pl-kos">,</span>
            <span class="pl-c1">_container</span>: null<span class="pl-kos">,</span>
        <span class="pl-kos">}</span><span class="pl-kos">;</span>

        <span class="pl-c">// buton title</span>
        <span class="pl-k">const</span> <span class="pl-s1">titleList</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">en</span>: <span class="pl-s">'Audio'</span><span class="pl-kos">,</span>
            <span class="pl-c1">ko</span>: <span class="pl-s">'오디오'</span>
        <span class="pl-kos">}</span><span class="pl-kos">;</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">title</span> <span class="pl-c1">=</span> <span class="pl-s1">titleList</span><span class="pl-kos">[</span><span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">.</span><span class="pl-c1">code</span><span class="pl-kos">]</span><span class="pl-kos">;</span>

        <span class="pl-c">// languages</span>
        <span class="pl-k">const</span> <span class="pl-s1">customAudioLang</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">en</span>: <span class="pl-kos">{</span>
                <span class="pl-c1">title</span>: <span class="pl-s">'Audio'</span><span class="pl-kos">,</span>
                <span class="pl-c1">file</span>: <span class="pl-s">'Select from files'</span><span class="pl-kos">,</span>
                <span class="pl-c1">url</span>: <span class="pl-s">'Audio url'</span>
            <span class="pl-kos">}</span><span class="pl-kos">,</span>
            <span class="pl-c1">ko</span>: <span class="pl-kos">{</span>
                <span class="pl-c1">title</span>: <span class="pl-s">'오디오'</span><span class="pl-kos">,</span>
                <span class="pl-c1">file</span>: <span class="pl-s">'파일에서 선택'</span><span class="pl-kos">,</span>
                <span class="pl-c1">url</span>: <span class="pl-s">'오디오 주소'</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">}</span><span class="pl-kos">;</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">.</span><span class="pl-c1">audio</span> <span class="pl-c1">=</span> <span class="pl-s1">customAudioLang</span><span class="pl-kos">[</span><span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">.</span><span class="pl-c1">code</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
        
        <span class="pl-c">/** dialog */</span>
        <span class="pl-k">let</span> <span class="pl-s1">audio_dialog</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setDialog</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">modal</span> <span class="pl-c1">=</span> <span class="pl-s1">audio_dialog</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">fileInput</span> <span class="pl-c1">=</span> <span class="pl-s1">audio_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'._se_audio_files'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span> <span class="pl-c1">=</span> <span class="pl-s1">audio_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'.se-input-url'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">focusElement</span> <span class="pl-c1">=</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">fileInput</span><span class="pl-kos">;</span>

        <span class="pl-c">/** controller */</span>
        <span class="pl-k">let</span> <span class="pl-s1">audio_controller</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setController</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">controller</span> <span class="pl-c1">=</span> <span class="pl-s1">audio_controller</span><span class="pl-kos">;</span>

        <span class="pl-c">/** add event listeners */</span>
        <span class="pl-s1">audio_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'.se-dialog-files-edge-button'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'click'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">_removeSelectedFiles</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">fileInput</span><span class="pl-kos">,</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">audio_dialog</span><span class="pl-kos">.</span><span class="pl-en">querySelector</span><span class="pl-kos">(</span><span class="pl-s">'form'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'submit'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">submit</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">audio_controller</span><span class="pl-kos">.</span><span class="pl-en">addEventListener</span><span class="pl-kos">(</span><span class="pl-s">'click'</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">onClick_controller</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-s1">core</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/** append html */</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">modal</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">audio_dialog</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/** append controller */</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">relative</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">audio_controller</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">/** empty memory */</span>
        <span class="pl-s1">audio_dialog</span> <span class="pl-c1">=</span> null<span class="pl-kos">,</span> <span class="pl-s1">audio_controller</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/** HTML - dialog */</span>
    <span class="pl-en">setDialog</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-smi">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">lang</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">dialog</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'DIV'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-s1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">className</span> <span class="pl-c1">=</span> <span class="pl-s">'se-dialog-content'</span><span class="pl-kos">;</span>
        <span class="pl-s1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">display</span> <span class="pl-c1">=</span> <span class="pl-s">'none'</span><span class="pl-kos">;</span>
        <span class="pl-k">let</span> <span class="pl-s1">html</span> <span class="pl-c1">=</span> <span class="pl-s">''</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;form class="editor_link"&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-dialog-header"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="button" data-command="close" class="se-btn se-dialog-close" aria-label="Close" title="'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">close</span> <span class="pl-c1">+</span> <span class="pl-s">'"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">icons</span><span class="pl-kos">.</span><span class="pl-c1">cancel</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;span class="se-modal-title"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">audio</span><span class="pl-kos">.</span><span class="pl-c1">title</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-dialog-body"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div class="se-dialog-form"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;label&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">audio</span><span class="pl-kos">.</span><span class="pl-c1">file</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/label&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;div class="se-dialog-form-files"&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;input class="se-input-form _se_audio_files" type="file" accept="audio/*" multiple="multiple" /&gt;'</span> <span class="pl-c1">+</span>
                            <span class="pl-s">'&lt;button type="button" data-command="filesRemove" class="se-btn se-dialog-files-edge-button" title="'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">.</span><span class="pl-c1">remove</span> <span class="pl-c1">+</span> <span class="pl-s">'"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">icons</span><span class="pl-kos">.</span><span class="pl-c1">cancel</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;div class="se-dialog-form"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;label&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">audio</span><span class="pl-kos">.</span><span class="pl-c1">url</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/label&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;input class="se-input-form se-input-url" type="text" /&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-dialog-footer"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="submit" class="se-btn-primary" title="'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">submitButton</span> <span class="pl-c1">+</span> <span class="pl-s">'"&gt;&lt;span&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">dialogBox</span><span class="pl-kos">.</span><span class="pl-c1">submitButton</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;/form&gt;'</span><span class="pl-kos">;</span>

        <span class="pl-s1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">innerHTML</span> <span class="pl-c1">=</span> <span class="pl-s1">html</span><span class="pl-kos">;</span>

        <span class="pl-k">return</span> <span class="pl-s1">dialog</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/** HTML - controller */</span>
    <span class="pl-en">setController</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-smi">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">lang</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">lang</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">icons</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">icons</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">link_btn</span> <span class="pl-c1">=</span> <span class="pl-smi">core</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'DIV'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-s1">link_btn</span><span class="pl-kos">.</span><span class="pl-c1">className</span> <span class="pl-c1">=</span> <span class="pl-s">'se-controller se-controller-link'</span><span class="pl-kos">;</span>
        <span class="pl-s1">link_btn</span><span class="pl-kos">.</span><span class="pl-c1">innerHTML</span> <span class="pl-c1">=</span> <span class="pl-s">''</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;div class="se-arrow se-arrow-up"&gt;&lt;/div&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;div class="link-content"&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;div class="se-btn-group"&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="button" data-command="update" tabindex="-1" class="se-tooltip"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">edit</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;&lt;span class="se-tooltip-text"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">.</span><span class="pl-c1">edit</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;button type="button" data-command="delete" tabindex="-1" class="se-tooltip"&gt;'</span> <span class="pl-c1">+</span>
                        <span class="pl-s1">icons</span><span class="pl-kos">.</span><span class="pl-c1">delete</span> <span class="pl-c1">+</span>
                        <span class="pl-s">'&lt;span class="se-tooltip-inner"&gt;&lt;span class="se-tooltip-text"&gt;'</span> <span class="pl-c1">+</span> <span class="pl-s1">lang</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">.</span><span class="pl-c1">remove</span> <span class="pl-c1">+</span> <span class="pl-s">'&lt;/span&gt;&lt;/span&gt;'</span> <span class="pl-c1">+</span>
                    <span class="pl-s">'&lt;/button&gt;'</span> <span class="pl-c1">+</span>
                <span class="pl-s">'&lt;/div&gt;'</span> <span class="pl-c1">+</span>
            <span class="pl-s">'&lt;/div&gt;'</span><span class="pl-kos">;</span>

        <span class="pl-k">return</span> <span class="pl-s1">link_btn</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// Disable url input when uploading files</span>
    <span class="pl-en">_removeSelectedFiles</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">urlInput</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">urlInput</span><span class="pl-kos">)</span> <span class="pl-s1">urlInput</span><span class="pl-kos">.</span><span class="pl-en">removeAttribute</span><span class="pl-kos">(</span><span class="pl-s">'disabled'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span> <span class="pl-k">@Override</span> fileManager</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">fileTags</span>: <span class="pl-kos">[</span><span class="pl-s">'audio'</span><span class="pl-kos">]</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Override</span> core, fileManager, resizing</span>
<span class="pl-c">     * <span class="pl-k">@description</span> It is called from core.selectComponent.</span>
<span class="pl-c">     * <span class="pl-k">@param</span> {<span class="pl-smi">Element</span>} element Target element</span>
<span class="pl-c">     */</span>
    <span class="pl-en">select</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">onModifyMode</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">element</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Override</span> fileManager, resizing </span>
<span class="pl-c">     * <span class="pl-k">@param</span> {<span class="pl-smi">Element</span>} element Target element</span>
<span class="pl-c">     */</span>
    <span class="pl-en">destroy</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">element</span> <span class="pl-c1">=</span> <span class="pl-s1">element</span> <span class="pl-c1">||</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">container</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getParentElement</span><span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-c1">isComponent</span><span class="pl-kos">)</span> <span class="pl-c1">||</span> <span class="pl-s1">element</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">dataIndex</span> <span class="pl-c1">=</span> <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-en">getAttribute</span><span class="pl-kos">(</span><span class="pl-s">'data-index'</span><span class="pl-kos">)</span> * <span class="pl-c1">1</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">focusEl</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">container</span><span class="pl-kos">.</span><span class="pl-c1">previousElementSibling</span> <span class="pl-c1">||</span> <span class="pl-s1">container</span><span class="pl-kos">.</span><span class="pl-c1">nextElementSibling</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">emptyDiv</span> <span class="pl-c1">=</span> <span class="pl-s1">container</span><span class="pl-kos">.</span><span class="pl-c1">parentNode</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">removeItem</span><span class="pl-kos">(</span><span class="pl-s1">container</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">init</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">controllersOff</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">emptyDiv</span> !== <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">wysiwyg</span><span class="pl-kos">)</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">removeItemAllParents</span><span class="pl-kos">(</span><span class="pl-s1">emptyDiv</span><span class="pl-kos">,</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">current</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-k">return</span> <span class="pl-s1">current</span><span class="pl-kos">.</span><span class="pl-c1">childNodes</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span><span class="pl-kos">;</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> null<span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// focus</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">focusEdge</span><span class="pl-kos">(</span><span class="pl-s1">focusEl</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// fileManager event</span>
        <span class="pl-c">// (pluginName, data-index, "uploadEventHandler")</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">fileManager</span><span class="pl-kos">.</span><span class="pl-c1">deleteInfo</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span> <span class="pl-s1">dataIndex</span><span class="pl-kos">,</span> <span class="pl-s1" style="color: #20ac40;">userFunc_audioUpload</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// history stack</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">history</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Override</span> fileManager</span>
<span class="pl-c">     */</span>
    <span class="pl-en">checkFileInfo</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// (pluginName, [tag], "uploadEventHandler", "formatFixFunction", "using resizing module?")</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">fileManager</span><span class="pl-kos">.</span><span class="pl-c1">checkInfo</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">'audio'</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-s1" style="color: #20ac40;">userFunc_audioUpload</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">updateCover</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Override</span> fileManager</span>
<span class="pl-c">     */</span>
    <span class="pl-en">resetFileInfo</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// (pluginName, data-index, "uploadEventHandler")</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">fileManager</span><span class="pl-kos">.</span><span class="pl-c1">resetInfo</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span> <span class="pl-s1" style="color: #20ac40;">userFunc_audioUpload</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span> <span class="pl-k">@Override</span> dialog</span>
<span class="pl-c">     * This method is called just before the dialog opens.</span>
<span class="pl-c">     * <span class="pl-k">@param</span> {<span class="pl-smi">Boolean</span>} update If "update" argument is true, it is not a new call, but a call to modify an already created element.</span>
<span class="pl-c">     */</span>
    <span class="pl-en">on</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">update</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">update</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">init</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-c">// "update" and "this.context.dialog.updateModal" are always the same value.</span>
            <span class="pl-c">// This code is an exception to the "link" plugin.</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">updateModal</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">.</span><span class="pl-c1">src</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span> <span class="pl-k">@Override</span> dialog</span>
<span class="pl-c">     * This method is called when the plugin button is clicked.</span>
<span class="pl-c">     * Open the modal window here.</span>
<span class="pl-c">     */</span>
    <span class="pl-en">open</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// open.call(core, pluginName, isModify)</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">open</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span> <span class="pl-c1">===</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">currentControllerName</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">submit</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>

        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">preventDefault</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">stopPropagation</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">try</span> <span class="pl-kos">{</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">fileInput</span><span class="pl-kos">.</span><span class="pl-c1">files</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-c">// upload files</span>
                <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">submitAction</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">fileInput</span><span class="pl-kos">.</span><span class="pl-c1">files</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">.</span><span class="pl-en">trim</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-c">// url</span>
                <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">setupUrl</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">throw</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">'[SUNEDITOR.audio.submit.fail] cause : "'</span> <span class="pl-c1">+</span> <span class="pl-s1">error</span><span class="pl-kos">.</span><span class="pl-c1">message</span> <span class="pl-c1">+</span> <span class="pl-s">'"'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">finally</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">close</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">submitAction</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">fileList</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">fileList</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-k">return</span><span class="pl-kos">;</span>

        <span class="pl-k">let</span> <span class="pl-s1">fileSize</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">files</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
        <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">len</span> <span class="pl-c1">=</span> <span class="pl-s1">fileList</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">len</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-pds">/audio/i</span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">fileList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">type</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-s1">files</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s1">fileList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                <span class="pl-s1">fileSize</span> <span class="pl-c1">+=</span> <span class="pl-s1">fileList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">size</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">}</span>

        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">audioPlugin</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>

        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_uploadFileLength</span> <span class="pl-c1">=</span> <span class="pl-s1">files</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">filesLen</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">updateModal</span> ? <span class="pl-c1">1</span> : <span class="pl-s1">files</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">info</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
            <span class="pl-c1">isUpdate</span>: <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">updateModal</span><span class="pl-kos">,</span>
            <span class="pl-c1">element</span>: <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_element</span>
        <span class="pl-kos">}</span><span class="pl-kos">;</span>

        <span class="pl-c">// create formData</span>
        <span class="pl-k">const</span> <span class="pl-s1">formData</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">FormData</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">filesLen</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">formData</span><span class="pl-kos">.</span><span class="pl-en">append</span><span class="pl-kos">(</span><span class="pl-s">'file-'</span> <span class="pl-c1">+</span> <span class="pl-s1">i</span><span class="pl-kos">,</span> <span class="pl-s1">files</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-c">// fileManager - upload</span>
        <span class="pl-c">// (uploadURL, uploadHeader, formData, callBack, errorCallBack)</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">fileManager</span><span class="pl-kos">.</span><span class="pl-c1">upload</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'http://localhost:3000'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s1">formData</span><span class="pl-kos">,</span> <span class="pl-s1">audioPlugin</span><span class="pl-kos">.</span><span class="pl-c1">callBack_upload</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">info</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s1">audioPlugin</span><span class="pl-kos">.</span><span class="pl-c1">callBack_error</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">callBack_upload</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">info</span><span class="pl-kos">,</span> <span class="pl-s1">xmlHttp</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">response</span> <span class="pl-c1">=</span> <span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-s1">xmlHttp</span><span class="pl-kos">.</span><span class="pl-c1">responseText</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">response</span><span class="pl-kos">.</span><span class="pl-c1">errorMessage</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">functions</span><span class="pl-kos">.</span><span class="pl-en">noticeOpen</span><span class="pl-kos">(</span><span class="pl-s1">response</span><span class="pl-kos">.</span><span class="pl-c1">errorMessage</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-k">const</span> <span class="pl-s1">fileList</span> <span class="pl-c1">=</span> <span class="pl-s1">response</span><span class="pl-kos">.</span><span class="pl-c1">result</span><span class="pl-kos">;</span>
            <span class="pl-k">let</span> <span class="pl-s1">oAudio</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>
            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">info</span><span class="pl-kos">.</span><span class="pl-c1">isUpdate</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-s1">oAudio</span> <span class="pl-c1">=</span> <span class="pl-s1">info</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
                <span class="pl-s1">oAudio</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'AUDIO'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
                <span class="pl-s1">oAudio</span><span class="pl-kos">.</span><span class="pl-en">setAttribute</span><span class="pl-kos">(</span><span class="pl-s">'controls'</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>

            <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">len</span> <span class="pl-c1">=</span> <span class="pl-s1">fileList</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">,</span> <span class="pl-s1">file</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">len</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-s1">file</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s1">fileList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">,</span> <span class="pl-c1">size</span>: <span class="pl-s1">fileList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">size</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
                <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">create_audio</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">oAudio</span><span class="pl-kos">,</span> <span class="pl-s1">fileList</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">.</span><span class="pl-c1">url</span><span class="pl-kos">,</span> <span class="pl-s1">file</span><span class="pl-kos">,</span> <span class="pl-s1">info</span><span class="pl-kos">.</span><span class="pl-c1">isUpdate</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">callBack_error</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">errorMessage</span><span class="pl-kos">,</span> <span class="pl-s1">response</span><span class="pl-kos">,</span> <span class="pl-s1">core</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">core</span><span class="pl-kos">.</span><span class="pl-c1">functions</span><span class="pl-kos">.</span><span class="pl-en">noticeOpen</span><span class="pl-kos">(</span><span class="pl-s1">errorMessage</span> | <span class="pl-s1">response</span><span class="pl-kos">.</span><span class="pl-en">toString</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">setupUrl</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">try</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">showLoading</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">src</span> <span class="pl-c1">=</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">.</span><span class="pl-en">trim</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

            <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">src</span><span class="pl-kos">.</span><span class="pl-c1">length</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span>

            <span class="pl-k">const</span> <span class="pl-s1">oAudio</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'AUDIO'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-s1">oAudio</span><span class="pl-kos">.</span><span class="pl-en">setAttribute</span><span class="pl-kos">(</span><span class="pl-s">'controls'</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

            <span class="pl-c">// When opened for modification "this.context.dialog.updateModal" is true</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">create_audio</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">oAudio</span><span class="pl-kos">,</span> <span class="pl-s1">src</span><span class="pl-kos">,</span> null<span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">updateModal</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">catch</span> <span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">throw</span> <span class="pl-v">Error</span><span class="pl-kos">(</span><span class="pl-s">'[SUNEDITOR.audio.audio.fail] cause : "'</span> <span class="pl-c1">+</span> <span class="pl-s1">error</span><span class="pl-kos">.</span><span class="pl-c1">message</span> <span class="pl-c1">+</span> <span class="pl-s">'"'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">finally</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">closeLoading</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// create or update</span>
    <span class="pl-en">create_audio</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-s1">src</span><span class="pl-kos">,</span> <span class="pl-s1">file</span><span class="pl-kos">,</span> <span class="pl-s1">isUpdate</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>
        
        <span class="pl-c">// create new tag</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">isUpdate</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-c1">src</span> <span class="pl-c1">=</span> <span class="pl-s1">src</span><span class="pl-kos">;</span>

            <span class="pl-c">// In order to use it in the form of components such as images and videos, </span>
            <span class="pl-c">// you need to create component tags by calling the "set_cover" and "set_container" functions of the "component" module.</span>
            <span class="pl-k">const</span> <span class="pl-s1">cover</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">component</span><span class="pl-kos">.</span><span class="pl-c1">set_cover</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">element</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">container</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">component</span><span class="pl-kos">.</span><span class="pl-c1">set_container</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">cover</span><span class="pl-kos">,</span> <span class="pl-s">''</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">insertComponent</span><span class="pl-kos">(</span><span class="pl-s1">container</span><span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-c">// update</span>
        <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">element</span><span class="pl-s1"> && </span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">src</span> !== <span class="pl-s1">src</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">element</span> <span class="pl-c1">=</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">;</span>
            <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-c1">src</span> <span class="pl-c1">=</span> <span class="pl-s1">src</span>
        <span class="pl-kos">}</span> <span class="pl-c">// not changed</span>
        <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-k">return</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-c">// call fileManager.setInfo when updated tag</span>
        <span class="pl-c">// (pluginName, element, "uploadEventHandler", file, "using resizing module")</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">fileManager</span><span class="pl-kos">.</span><span class="pl-c1">setInfo</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span> <span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-s1" style="color: #20ac40;">userFunc_audioUpload</span><span class="pl-kos">,</span> <span class="pl-s1">file</span><span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">history</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">// Update container for "audio" tag not matching format to be used in "checkFileInfo"</span>
    <span class="pl-en">updateCover</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>
        <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-en">setAttribute</span><span class="pl-kos">(</span><span class="pl-s">'controls'</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        
        <span class="pl-c">// find component element</span>
        <span class="pl-k">const</span> <span class="pl-s1">existElement</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getParentElement</span><span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-c1">isMediaComponent</span><span class="pl-kos">)</span> <span class="pl-c1">||</span> 
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getParentElement</span><span class="pl-kos">(</span><span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">current</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">isWysiwygDiv</span><span class="pl-kos">(</span><span class="pl-s1">current</span><span class="pl-kos">.</span><span class="pl-c1">parentNode</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// clone element</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_element</span> <span class="pl-c1">=</span> <span class="pl-s1">element</span> <span class="pl-c1">=</span> <span class="pl-s1">element</span><span class="pl-kos">.</span><span class="pl-en">cloneNode</span><span class="pl-kos">(</span><span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">cover</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">component</span><span class="pl-kos">.</span><span class="pl-c1">set_cover</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">element</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">container</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">component</span><span class="pl-kos">.</span><span class="pl-c1">set_container</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">cover</span><span class="pl-kos">,</span> <span class="pl-s">'se-video-container'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-s1">existElement</span><span class="pl-kos">.</span><span class="pl-c1">parentNode</span><span class="pl-kos">.</span><span class="pl-en">replaceChild</span><span class="pl-kos">(</span><span class="pl-s1">container</span><span class="pl-kos">,</span> <span class="pl-s1">existElement</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// call fileManager.setInfo when updated tag</span>
        <span class="pl-c">// (pluginName, element, "uploadEventHandler", file, "using resizing module")</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">fileManager</span><span class="pl-kos">.</span><span class="pl-c1">setInfo</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span> <span class="pl-s1">element</span><span class="pl-kos">,</span> <span class="pl-s1" style="color: #20ac40;">userFunc_audioUpload</span><span class="pl-kos">,</span> null<span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span> <span class="pl-k">@Override</span> fileManager, resizing</span>
<span class="pl-c">     * <span class="pl-k">@param</span> {<span class="pl-smi">Element</span>} selectionTag Selected element</span>
<span class="pl-c">     * <span class="pl-k">@param</span> {<span class="pl-smi">Object</span>} size Size object{w, h, t, 1} of "core.plugins.resizing.call_controller_resize" return value when if using "resizing" module</span>
<span class="pl-c">     */</span>
    <span class="pl-en">onModifyMode</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">selectionTag</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">controller</span> <span class="pl-c1">=</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">;</span>
        <span class="pl-k">const</span> <span class="pl-s1">offset</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getOffset</span><span class="pl-kos">(</span><span class="pl-s1">selectionTag</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">wysiwygFrame</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">top</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">offset</span><span class="pl-kos">.</span><span class="pl-c1">top</span> <span class="pl-c1">+</span> <span class="pl-s1">selectionTag</span><span class="pl-kos">.</span><span class="pl-c1">offsetHeight</span> <span class="pl-c1">+</span> <span class="pl-c1">10</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>
        <span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">offset</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">-</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">wysiwygFrame</span><span class="pl-kos">.</span><span class="pl-c1">scrollLeft</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>

        <span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">display</span> <span class="pl-c1">=</span> <span class="pl-s">'block'</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">overLeft</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">element</span><span class="pl-kos">.</span><span class="pl-c1">wysiwygFrame</span><span class="pl-kos">.</span><span class="pl-c1">offsetWidth</span> <span class="pl-c1">-</span> <span class="pl-kos">(</span><span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">offsetLeft</span> <span class="pl-c1">+</span> <span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">offsetWidth</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">overLeft</span> <span class="pl-c1">&lt;</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">offsetLeft</span> <span class="pl-c1">+</span> <span class="pl-s1">overLeft</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>
            <span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">firstElementChild</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-c1">20</span> <span class="pl-c1">-</span> <span class="pl-s1">overLeft</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-s">'px'</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
            <span class="pl-s1">controller</span><span class="pl-kos">.</span><span class="pl-c1">firstElementChild</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">left</span> <span class="pl-c1">=</span> <span class="pl-s">'20px'</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
        
        <span class="pl-c">// Show controller at editor area (controller elements, function, "controller target element(@Required)", "controller name(@Required)", etc..)</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">controllersOn</span><span class="pl-kos">(</span><span class="pl-s1">controller</span><span class="pl-kos">,</span> <span class="pl-s1">selectionTag</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">init</span><span class="pl-kos">.</span><span class="pl-en">bind</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-c">// set modify mode context</span>
        <span class="pl-s1">selectionTag</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">border</span> <span class="pl-c1">=</span> <span class="pl-s">'1px solid #80bdff'</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_element</span> <span class="pl-c1">=</span> <span class="pl-s1">selectionTag</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_cover</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getParentElement</span><span class="pl-kos">(</span><span class="pl-s1">selectionTag</span><span class="pl-kos">,</span> <span class="pl-s">'FIGURE'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_container</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-en">getParentElement</span><span class="pl-kos">(</span><span class="pl-s1">selectionTag</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">util</span><span class="pl-kos">.</span><span class="pl-c1">isComponent</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span> <span class="pl-k">@Override</span> fileManager, resizing</span>
<span class="pl-c">     */</span>
    <span class="pl-en">openModify</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">notOpen</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">.</span><span class="pl-c1">src</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">notOpen</span><span class="pl-kos">)</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">open</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s">'customAudio'</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-en">onClick_controller</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">stopPropagation</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">command</span> <span class="pl-c1">=</span> <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-c1">target</span><span class="pl-kos">.</span><span class="pl-en">getAttribute</span><span class="pl-kos">(</span><span class="pl-s">'data-command'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span>!<span class="pl-s1">command</span><span class="pl-kos">)</span> <span class="pl-k">return</span><span class="pl-kos">;</span>

        <span class="pl-s1">e</span><span class="pl-kos">.</span><span class="pl-en">preventDefault</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-pds">/update/</span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">command</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">openModify</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
        <span class="pl-k">else</span> <span class="pl-kos">{</span> <span class="pl-c">/** delete */</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">plugins</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">destroy</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>

        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">controllersOff</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-c">/**</span>
<span class="pl-c">     * <span class="pl-k">@Required</span> <span class="pl-k">@Override</span> dialog</span>
<span class="pl-c">     * This method is called when the dialog window is closed.</span>
<span class="pl-c">     * Initialize the properties.</span>
<span class="pl-c">     */</span>
    <span class="pl-en">init</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">dialog</span><span class="pl-kos">.</span><span class="pl-c1">updateModal</span><span class="pl-kos">)</span> <span class="pl-k">return</span><span class="pl-kos">;</span>

        <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">context</span><span class="pl-kos">.</span><span class="pl-c1">customAudio</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">)</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_element</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">border</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">controller</span><span class="pl-kos">.</span><span class="pl-c1">style</span><span class="pl-kos">.</span><span class="pl-c1">display</span> <span class="pl-c1">=</span> <span class="pl-s">'none'</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">_element</span> <span class="pl-c1">=</span> null<span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">fileInput</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
        <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-c1">urlInput</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>

<div class="highlight highlight-source-js"><pre><span class="pl-c1">SUNEDITOR</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s">'ex_dialog_component_fileManager'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span><span class="pl-s1">plugin_dialog_component_fileManager</span><span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-c1">buttonList</span>: <span class="pl-kos">[</span>
        <span class="pl-kos">[ </span><span class="pl-s">'customAudio'</span>, <span class="pl-s">'preview'</span><span class="pl-kos"> ]</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
        </ddiv>
    </article>

    <footer>
        <p>SunEditor distributed under the MIT license.</p>
        <p><a href="https://github.com/JiHong88/SunEditor" target="_blank" style="color:#f4b124;">Go to GitHub SunEditor</a></p>
    </footer>
</div>

<script src="../js/common.js"></script>
<!-- suneditor -->
<script src="../../dist/suneditor.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/dialog.js"></script>
<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/component.js"></script>
<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/fileManager.js"></script>
<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/plugins/modules/resizing.js"></script>
<!-- <script src="../../src/plugins/modules/dialog.js"></script>
<script src="../../src/plugins/modules/component.js"></script>
<script src="../../src/plugins/modules/fileManager.js"></script>
<script src="../../src/plugins/modules/resizing.js"></script> -->
<script>
    var acc = document.getElementsByClassName("accordion");
    var i;
    for (i = 0; i < acc.length; i++) {
        acc[i].addEventListener("click", function() {
            this.classList.toggle("active");
            var panel = this.nextElementSibling;
            if (panel.style.maxHeight) {
                panel.style.maxHeight = null;
                panel.style.display = 'none';
            } else {
                panel.style.display = 'block';
                panel.style.maxHeight = panel.scrollHeight + "px";
            } 
        });
    }

    // ex) Adds a container of type "submenu" that contains a plugin.
    var custom_container = {
        // @Required @Unique
        // plugin name
        name: 'custom_container',

        // @Required
        // data display
        display: 'container',

        // @Required
        // add function - It is called only once when the plugin is first run.
        // This function generates HTML to append and register the event.
        // arguments - (core : core object, targetElement : clicked button element)
        add: function (core, targetElement) {

            // @Required
            // Registering a namespace for caching as a plugin name in the context object
            const context = core.context;
            context.custom_container = {};

            // Generate submenu HTML
            // Always bind "core" when calling a plugin function
            let listDiv = this.setSubmenu(core);

            // You must bind "core" object when registering an event.
            /** add event listeners */
            listDiv.querySelector('.se-form-group').addEventListener('click', this.onClick.bind(core));

            // @Required
            // You must add the "submenu" element using the "core.initMenuTarget" method.
            /** append target button menu */
            core.initMenuTarget(this.name, targetElement, listDiv);
        },

        setSubmenu: function (core) {
            const listDiv = core.util.createElement('DIV');
            const icons = core.icons; // assets/defaultIcons.js
            listDiv.className = 'se-menu-container se-submenu se-list-layer';
            listDiv.innerHTML = '' +
                '<div class="se-list-inner">' +
                    '<div class="se-form-group">' +
                        // @Required
                        // The "position" style of each element surrounding the button must be "relative".
                        // suneditor.css: .sun-editor .se-form-group > div {position:relative;}
                        '<div>' +
                            // @Required
                            // Enter the button name of the plug-in or default command in the button's "data-command"
                            '<button type="button" class="se-btn se-tooltip" data-command="bold" style="margin: 0 !important;">' +
                                icons.bold +
                                '<span class="se-tooltip-inner">' +
                                    '<span class="se-tooltip-text">Quote</span>' +
                                '</span>' +
                            '</button>' +
                        '</div>' +
                        '<div>' +
                            '<button type="button" class="se-btn se-tooltip" data-command="blockquote">' +
                                icons.blockquote +
                                '<span class="se-tooltip-inner">' +
                                    '<span class="se-tooltip-text">Quote</span>' +
                                '</span>' +
                            '</button>' +
                        '</div>' +
                        '<div>' +
                            '<button type="button" class="se-btn se-tooltip" data-command="link">' +
                                icons.link +
                                '<span class="se-tooltip-inner">' +
                                    '<span class="se-tooltip-text">Link</span>' +
                                '</span>' +
                            '</button>' +
                        '</div>' +
                        '<div>' +
                            '<button type="button" class="se-btn se-tooltip" data-command="table">' +
                                icons.table +
                                '<span class="se-tooltip-inner">' +
                                    '<span class="se-tooltip-text">Table</span>' +
                                '</span>' +
                            '</button>' +
                        '</div>' +
                        '<div>' +
                            '<button type="button" class="se-btn se-tooltip" data-command="textStyle">' +
                                icons.text_style +
                                '<span class="se-tooltip-inner">' +
                                    '<span class="se-tooltip-text">Text style</span>' +
                                '</span>' +
                            '</button>' +
                        '</div>' +
                    '</div>' +
                '</div>';

            return listDiv;
        },

        onClick: function (e) {
            e.preventDefault();
            e.stopPropagation();

            let target = e.target;
            let command = '';

            while (!command && !/^UL$/i.test(target.tagName)) {
                command = target.getAttribute('data-command');
                if (command) break;
                target = target.parentNode;
            }

            if (!command) return;

            const plugin = this.plugins[command];
            this.actionCall(command, (plugin ? plugin.display : ''), target);
        }
    };

    // ex) A command plugin to add "Range format element(util.isRangeFormatElement)" to selection
    var plugin_command = {
        // @Required @Unique
        // plugin name
        name: 'customCommand',
        // @Required
        // data display
        display: 'command',

        //@Options
        title: 'Add range tag', 
        buttonClass: '', 
        innerHTML: '<i class="fas fa-carrot"></i>',

        // @Required
        // add function - It is called only once when the plugin is first run.
        // This function generates HTML to append and register the event.
        // arguments - (core : core object, targetElement : clicked button element)
        add: function (core, targetElement) {
            const context = core.context;
            const rangeTag = core.util.createElement('div');
            core.util.addClass(rangeTag, '__se__format__range_custom');

            // @Required
            // Registering a namespace for caching as a plugin name in the context object
            context.customCommand = {
                targetButton: targetElement,
                tag: rangeTag
            };
        },

        // @Override core
        // Plugins with active methods load immediately when the editor loads.
        // Called each time the selection is moved.
        active: function (element) {
            if (!element) {
                this.util.removeClass(this.context.customCommand.targetButton, 'active');
            } else if (this.util.hasClass(element, '__se__format__range_custom')) {
                this.util.addClass(this.context.customCommand.targetButton, 'active');
                return true;
            }
            
            return false;
        },

        // @Required, @Override core
        // The behavior of the "command plugin" must be defined in the "action" method.
        action: function () {
            const rangeTag = this.util.getRangeFormatElement(this.getSelectionNode());

            if (this.util.hasClass(rangeTag, '__se__format__range_custom')) {
                this.detachRangeFormatElement(rangeTag, null, null, false, false);
            } else {
                this.applyRangeFormatElement(this.context.customCommand.tag.cloneNode(false));
            }
        }
    }

    // ex) A command plugin to add "text node" to selection
    var plugin_command_2 = {
        name: 'customCommand_2',
        display: 'command',
        title:'Text node change', 
        buttonClass:'', 
        // This icon uses Font Awesome
        innerHTML:'<i class="fas fa-font"></i>',
        add: function (core, targetElement) {
            const context = core.context;
            context.customCommand_2 = {
                targetButton: targetElement
            };
        },
        active: function (element) {
            if (!element) {
                this.util.removeClass(this.context.customCommand_2.targetButton, 'active');
            } else if (/^mark$/i.test(element.nodeName) && element.style.backgroundColor.length > 0) {
                this.util.addClass(this.context.customCommand_2.targetButton, 'active');
                return true;
            }
            
            return false;
        },
        action: function () {
            if (!this.util.hasClass(this.context.customCommand_2.targetButton, 'active')) {
                const newNode = this.util.createElement('MARK');
                newNode.style.backgroundColor = 'hsl(60,75%,60%)';
                this.nodeChange(newNode, ['background-color'], null, null);
            } else {
                this.nodeChange(null, ['background-color'], ['mark'], true);
            }

            this.focus();
        }
    }


    // ex) A submenu plugin that appends the contents of the input element to the editor
    var plugin_submenu = {
        // @Required @Unique
        // plugin name
        name: 'custom_plugin_submenu',

        // @Required
        // data display
        display: 'submenu',

        // @Options
        title: 'Custom plugin of the submenu', 
        buttonClass: '', 
        innerHTML: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>',

        // @Required
        // add function - It is called only once when the plugin is first run.
        // This function generates HTML to append and register the event.
        // arguments - (core : core object, targetElement : clicked button element)
        add: function (core, targetElement) {

            // @Required
            // Registering a namespace for caching as a plugin name in the context object
            const context = core.context;
            context.customSubmenu = {
                targetButton: targetElement,
                textElement: null,
                currentSpan: null
            };

            // Generate submenu HTML
            // Always bind "core" when calling a plugin function
            let listDiv = this.setSubmenu(core);

            // Input tag caching
            context.customSubmenu.textElement = listDiv.querySelector('input');

            // You must bind "core" object when registering an event.
            /** add event listeners */
            listDiv.querySelector('.se-btn-primary').addEventListener('click', this.onClick.bind(core));
            listDiv.querySelector('.se-btn').addEventListener('click', this.onClickRemove.bind(core));

            // @Required
            // You must add the "submenu" element using the "core.initMenuTarget" method.
            /** append target button menu */
            core.initMenuTarget(this.name, targetElement, listDiv);
        },

        setSubmenu: function (core) {
            const listDiv = core.util.createElement('DIV');
            // @Required
            // A "se-submenu" class is required for the top level element.
            listDiv.className = 'se-menu-container se-submenu se-list-layer';
            listDiv.innerHTML = '' +
                '<div class="se-list-inner">' +
                    '<ul class="se-list-basic" style="width: 230px;">' +
                        '<li>' +
                            '<div class="se-form-group">' +
                                '<input class="se-input-form" type="text" placeholder="insert text" style="border: 1px solid #CCC;" />' +
                                '<button type="button" class="se-btn-primary se-tooltip">' +
                                    '<strong>OK</strong>' +
                                    '<span class="se-tooltip-inner">' +
                                        '<span class="se-tooltip-text">Append span</span>' +
                                    '</span>' +
                                '</button>' +
                                '<button type="button" class="se-btn se-tooltip">' +
                                    '<strong>X</strong>' +
                                    '<span class="se-tooltip-inner">' +
                                        '<span class="se-tooltip-text">Remove</span>' +
                                    '</span>' +
                                '</button>' +
                            '</div>' +
                        '</li>' +
                    '</ul>' +
                '</div>';

            return listDiv;
        },

        // @Override core
        // Plugins with active methods load immediately when the editor loads.
        // Called each time the selection is moved.
        active: function (element) {
            // If no tag matches, the "element" argument is called with a null value.
            if (!element) {
                this.util.removeClass(this.context.customSubmenu.targetButton, 'active');
                this.context.customSubmenu.textElement.value = '';
                this.context.customSubmenu.currentSpan = null;
            } else if (this.util.hasClass(element, 'se-custom-tag')) {
                this.util.addClass(this.context.customSubmenu.targetButton, 'active');
                this.context.customSubmenu.textElement.value = element.textContent;
                this.context.customSubmenu.currentSpan = element;
                return true;
            }
            
            return false;
        },

        // @Override submenu
        // Called after the submenu has been rendered
        on: function () {
            this.context.customSubmenu.textElement.focus();
        },

        onClickRemove: function () {
            const span = this.context.customSubmenu.currentSpan;
            if (span) {
                this.util.removeItem(span);
                this.context.customSubmenu.currentSpan = null;

                this.submenuOff();
                this.focus();
            }
        },

        onClick: function () {
            const value = this.context.customSubmenu.textElement.value.trim();
            if (!value) return;

            const span = this.context.customSubmenu.currentSpan;
            if (span) {
                span.textContent = value;
                this.setRange(span, 1, span, 1);
            } else {
                this.functions.insertHTML('<span class="se-custom-tag">' + value + '</span>', true);
                this.context.customSubmenu.textElement.value = '';
            }

            this.submenuOff();
        }
    };

    // ex) A link dialog plugin with multiple target options.
    var plugin_dialog = {
        // @Required @Unique
        // plugin name
        name: 'customLink',

        // @Required
        // data display
        display: 'dialog',

        // @Required
        // add function - It is called only once when the plugin is first run.
        // This function generates HTML to append and register the event.
        // arguments - (core : core object, targetElement : clicked button element)
        add: function (core) {

            // If you are using a module, you must register the module using the "addModule" method.
            core.addModule([SUNEDITOR_MODULES.dialog]);

            // @Required
            // Registering a namespace for caching as a plugin name in the context object
            const context = core.context;
            context.customLink = {
                focusElement: null, // @Override // This element has focus when the dialog is opened.
                targetSelect: null,
                linkAnchorText: null,
                _linkAnchor: null
            };

            /** link dialog */
            let link_dialog = this.setDialog(core);
            context.customLink.modal = link_dialog;
            context.customLink.focusElement = link_dialog.querySelector('._se_link_url');
            context.customLink.linkAnchorText = link_dialog.querySelector('._se_link_text');
            context.customLink.targetSelect = link_dialog.querySelector('.se-input-select');

            /** link controller */
            let link_controller = this.setController_LinkButton(core);
            context.customLink.linkController = link_controller;
            context.customLink._linkAnchor = null;

            /** add event listeners */
            link_dialog.querySelector('form').addEventListener('submit', this.submit.bind(core));
            link_controller.addEventListener('click', this.onClick_linkController.bind(core));

            /** append html */
            context.dialog.modal.appendChild(link_dialog);

            /** append controller */
            context.element.relative.appendChild(link_controller);

            /** empty memory */
            link_dialog = null, link_controller = null;
        },

        /** dialog */
        setDialog: function (core) {
            const lang = core.lang;
            const dialog = core.util.createElement('DIV');
            const targetList = [
                { target: '_blank', name: 'New window'},
                { target: '_parent', name: 'Parent frame'},
                { target: '_top', name: 'First frame', selected: true},
                { target: 'AnyFrame', name: 'Frame name'},
                { target: '_dialog', name: 'Self defined dialog'}
            ];

            dialog.className = 'se-dialog-content';
            dialog.style.display = 'none';
            let html = '' +
                '<form class="editor_link">' +
                    '<div class="se-dialog-header">' +
                        '<button type="button" data-command="close" class="se-btn se-dialog-close" aria-label="Close" title="' + lang.dialogBox.close + '">' +
                            core.icons.cancel +
                        '</button>' +
                        '<span class="se-modal-title">' + lang.dialogBox.linkBox.title + '</span>' +
                    '</div>' +
                    '<div class="se-dialog-body">' +
                        '<div class="se-dialog-form">' +
                            '<label>' + lang.dialogBox.linkBox.url + '</label>' +
                            '<input class="se-input-form _se_link_url" type="text" />' +
                        '</div>' +
                        '<div class="se-dialog-form">' +
                            '<label>' + lang.dialogBox.linkBox.text + '</label><input class="se-input-form _se_link_text" type="text" />' +
                        '</div>' +
                        '<div class="se-dialog-form se-dialog-form-footer">' +
                            '<select class="se-input-select" title="links">';
                                for (let i = 0, len = targetList.length, t, selected; i < len; i++) {
                                    t = targetList[i];
                                    selected = t.selected ? ' selected' : '';
                                    html += '<option value="' + t.target + '"' + selected + '>' + t.name + '</option>';
                                }
                            html += '</select>' +
                        '</div>' +
                    '</div>' +
                    '<div class="se-dialog-footer">' +
                        '<button type="submit" class="se-btn-primary" title="' + lang.dialogBox.submitButton + '"><span>' + lang.dialogBox.submitButton + '</span></button>' +
                    '</div>' +
                '</form>';


            dialog.innerHTML = html;

            return dialog;
        },

        /** modify controller button */
        setController_LinkButton: function (core) {
            const lang = core.lang;
            const icons = core.icons;
            const link_btn = core.util.createElement('DIV');

            link_btn.className = 'se-controller se-controller-link';
            link_btn.innerHTML = '' +
                '<div class="se-arrow se-arrow-up"></div>' +
                '<div class="link-content"><span><a target="_blank" href=""></a>&nbsp;</span>' +
                    '<div class="se-btn-group">' +
                        '<button type="button" data-command="update" tabindex="-1" class="se-tooltip">' +
                            icons.edit +
                            '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.edit + '</span></span>' +
                        '</button>' +
                        '<button type="button" data-command="unlink" tabindex="-1" class="se-tooltip">' +
                            icons.unlink +
                            '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.unlink + '</span></span>' +
                        '</button>' +
                        '<button type="button" data-command="delete" tabindex="-1" class="se-tooltip">' +
                            icons.delete +
                            '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.remove + '</span></span>' +
                        '</button>' +
                    '</div>' +
                '</div>';

            return link_btn;
        },

        // @Required, @Override dialog
        // This method is called when the plugin button is clicked.
        // Open the modal window here.
        open: function () {
            // open.call(core, pluginName, isModify)
            this.plugins.dialog.open.call(this, 'customLink', 'customLink' === this.currentControllerName);
        },

        submit: function (e) {
            this.showLoading();

            e.preventDefault();
            e.stopPropagation();

            const submitAction = function () {
                if (this.context.customLink.focusElement.value.trim().length === 0) return false;

                const contextLink = this.context.customLink;
                const url = contextLink.focusElement.value;
                const anchor = contextLink.linkAnchorText;
                const anchorText = anchor.value.length === 0 ? url : anchor.value;

                // When opened for modification "this.context.dialog.updateModal" is true
                if (!this.context.dialog.updateModal) {
                    const oA = this.util.createElement('A');
                    oA.href = url;
                    oA.textContent = anchorText;
                    oA.target = contextLink.targetSelect.selectedOptions[0].value;

                    const selectedFormats = this.getSelectedElements();
                    if (selectedFormats.length > 1) {
                        const oFormat = this.util.createElement(selectedFormats[0].nodeName);
                        oFormat.appendChild(oA);
                        this.insertNode(oFormat);
                    } else {
                        this.insertNode(oA);
                    }

                    this.setRange(oA.childNodes[0], 0, oA.childNodes[0], oA.textContent.length);
                } else {
                    contextLink._linkAnchor.href = url;
                    contextLink._linkAnchor.textContent = anchorText;
                    contextLink._linkAnchor.target = contextLink.targetSelect.selectedOptions[0].value;

                    // set range
                    this.setRange(contextLink._linkAnchor.childNodes[0], 0, contextLink._linkAnchor.childNodes[0], contextLink._linkAnchor.textContent.length);
                }

                // history stack
                this.history.push(false);

                contextLink.focusElement.value = '';
                contextLink.linkAnchorText.value = '';
            }.bind(this);

            try {
                submitAction();
            } finally {
                this.plugins.dialog.close.call(this);
                this.closeLoading();
                this.focus();
            }

            return false;
        },

        // @Override core
        // Plugins with active methods load immediately when the editor loads.
        // Called each time the selection is moved.
        active: function (element) {
            if (!element) {
                if (this.controllerArray.indexOf(this.context.customLink.linkController) > -1) {
                    this.controllersOff();
                }
            } else if (this.util.isAnchor(element) && element.getAttribute('data-image-link') === null) {
                if (this.controllerArray.indexOf(this.context.customLink.linkController) < 0) {
                    this.plugins.customLink.call_controller.call(this, element);
                }
                return true;
            }

            return false;
        },

        // @Override dialog
        // This method is called just before the dialog opens.
        // If "update" argument is true, it is not a new call, but a call to modify an already created element.
        on: function (update) {
            if (!update) {
                this.plugins.customLink.init.call(this);
                this.context.customLink.linkAnchorText.value = this.getSelection().toString();
            } else if (this.context.customLink._linkAnchor) {
                // "update" and "this.context.dialog.updateModal" are always the same value.
                // This code is an exception to the "link" plugin.
                this.context.dialog.updateModal = true;
                this.context.customLink.focusElement.value = this.context.customLink._linkAnchor.href;
                this.context.customLink.linkAnchorText.value = this.context.customLink._linkAnchor.textContent;
                this.context.customLink.targetSelect.value = this.context.customLink._linkAnchor.target || '';
            }
        },

        call_controller: function (selectionATag) {
            this.editLink = this.context.customLink._linkAnchor = selectionATag;
            const linkBtn = this.context.customLink.linkController;
            const link = linkBtn.querySelector('a');

            link.href = selectionATag.href;
            link.title = selectionATag.textContent;
            link.textContent = selectionATag.textContent;

            const offset = this.util.getOffset(selectionATag, this.context.element.wysiwygFrame);
            linkBtn.style.top = (offset.top + selectionATag.offsetHeight + 10) + 'px';
            linkBtn.style.left = (offset.left - this.context.element.wysiwygFrame.scrollLeft) + 'px';

            linkBtn.style.display = 'block';

            const overLeft = this.context.element.wysiwygFrame.offsetWidth - (linkBtn.offsetLeft + linkBtn.offsetWidth);
            if (overLeft < 0) {
                linkBtn.style.left = (linkBtn.offsetLeft + overLeft) + 'px';
                linkBtn.firstElementChild.style.left = (20 - overLeft) + 'px';
            } else {
                linkBtn.firstElementChild.style.left = '20px';
            }
            
            // Show controller at editor area (controller elements, function, "controller target element(@Required)", "controller name(@Required)", etc..)
            this.controllersOn(linkBtn, selectionATag, 'customLink');
        },

        onClick_linkController: function (e) {
            e.stopPropagation();

            const command = e.target.getAttribute('data-command');
            if (!command) return;

            e.preventDefault();

            if (/update/.test(command)) {
                const contextLink = this.context.customLink;
                contextLink.focusElement.value = contextLink._linkAnchor.href;
                contextLink.linkAnchorText.value = contextLink._linkAnchor.textContent;
                contextLink.targetSelect.value = contextLink.targetSelect.value;
                this.plugins.dialog.open.call(this, 'customLink', true);
            }
            else if (/unlink/.test(command)) {
                const sc = this.util.getChildElement(this.context.customLink._linkAnchor, function (current) { return current.childNodes.length === 0 || current.nodeType === 3; }, false);
                const ec = this.util.getChildElement(this.context.customLink._linkAnchor, function (current) { return current.childNodes.length === 0 || current.nodeType === 3; }, true);
                this.setRange(sc, 0, ec, ec.textContent.length);
                this.nodeChange(null, null, ['A'], false);
            }
            else {
                /** delete */
                this.util.removeItem(this.context.customLink._linkAnchor);
                this.context.customLink._linkAnchor = null;
                this.focus();

                // history stack
                this.history.push(false);
            }

            this.controllersOff();
        },

        // @Required, @Override dialog
        // This method is called when the dialog window is closed.
        // Initialize the properties.
        init: function () {
            const contextLink = this.context.customLink;
            contextLink.linkController.style.display = 'none';
            contextLink._linkAnchor = null;
            contextLink.focusElement.value = '';
            contextLink.linkAnchorText.value = '';
            contextLink.targetSelect.selectedIndex = 0;
        }
    };

    // audio list
    const audioTable = document.getElementById('audio_list');
    let audioList = [];

    function userFunc_audioUpload (targetElement, index, state, info, remainingFilesCount) {
        console.log('audioInfo', info);

        if (state === 'delete') {
            audioList.splice(findIndex(audioList, index), 1)
        } else {
            if (state === 'create') {
                audioList.push(info)
            } else { // update
                //
            }
        }

        if (remainingFilesCount === 0) {
            console.log('audioList', audioList)
            _setAudioList(audioList)
        }
    }

    function _setAudioList () {
        let list = '';

        for (let i = 0, info; i < audioList.length; i++) {
            info = audioList[i];
                
            list += '<li>' +
                        '<button title="delete" onclick="_selectAudio(\'delete\',' + info.index + ')">X</button>' +
                        '<a href="javascript:void(0)" onclick="_selectAudio(\'select\',' + info.index + ')">' + info.src + '</a>' +
                    '</li>';
        }

        audioTable.innerHTML = list;
    }

    function _selectAudio (type, index) {
        audioList[findIndex(audioList, index)][type]();
    }

    // ex) A link dialog plugin with used [dialog, component, fileManager] module
    // Sample audio : https://file-examples.com/index.php/sample-audio-files/
    var plugin_dialog_component_fileManager = {
        /**
         * @Required @Unique
         * plugin name
         */
        name: 'customAudio',

        /**
         * @Required
         * data display
         */
        display: 'dialog',

        /**
         * @options
         * You can also set from the button list
         */
        title:'Custom audio', 
        buttonClass:'', 
        innerHTML:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14,3.23V5.29C16.89,6.15 19,8.83 19,12C19,15.17 16.89,17.84 14,18.7V20.77C18,19.86 21,16.28 21,12C21,7.72 18,4.14 14,3.23M16.5,12C16.5,10.23 15.5,8.71 14,7.97V16C15.5,15.29 16.5,13.76 16.5,12M3,9V15H7L12,20V4L7,9H3Z" /></svg>',

        /**
         * @Required
         * add function - It is called only once when the plugin is first run.
         * This function generates HTML to append and register the event.
         * arguments - (core : core object, targetElement : clicked button element)
         */
        add: function (core) {

            // If you are using a module, you must register the module using the "addModule" method.
            core.addModule([SUNEDITOR_MODULES.dialog, SUNEDITOR_MODULES.component, SUNEDITOR_MODULES.fileManager]);

            /**
             * @Required
             * Registering a namespace for caching as a plugin name in the context object
             */
            const context = core.context;
            context.customAudio = {
                _infoList: [], // @Override fileManager
                _infoIndex: 0, // @Override fileManager
                _uploadFileLength: 0, // @Override fileManager
                focusElement: null, // @Override // This element has focus when the dialog is opened.
                targetSelect: null,
                linkAnchorText: null,
                // @require @Override component
                _element: null,
                _cover: null,
                _container: null,
            };

            // buton title
            const titleList = {
                en: 'Audio',
                ko: '오디오'
            };
            core.title = titleList[core.lang.code];

            // languages
            const customAudioLang = {
                en: {
                    title: 'Audio',
                    file: 'Select from files',
                    url: 'Audio url'
                },
                ko: {
                    title: '오디오',
                    file: '파일에서 선택',
                    url: '오디오 주소'
                }
            };
            core.lang.audio = customAudioLang[core.lang.code];
            
            /** dialog */
            let audio_dialog = this.setDialog(core);
            context.customAudio.modal = audio_dialog;
            context.customAudio.fileInput = audio_dialog.querySelector('._se_audio_files');
            context.customAudio.urlInput = audio_dialog.querySelector('.se-input-url');
            context.customAudio.focusElement = context.customAudio.fileInput;

            /** controller */
            let audio_controller = this.setController(core);
            context.customAudio.controller = audio_controller;

            /** add event listeners */
            audio_dialog.querySelector('.se-dialog-files-edge-button').addEventListener('click', this._removeSelectedFiles.bind(context.fileInput, context.urlInput));
            audio_dialog.querySelector('form').addEventListener('submit', this.submit.bind(core));
            audio_controller.addEventListener('click', this.onClick_controller.bind(core));

            /** append html */
            context.dialog.modal.appendChild(audio_dialog);

            /** append controller */
            context.element.relative.appendChild(audio_controller);

            /** empty memory */
            audio_dialog = null, audio_controller = null;
        },

        /** HTML - dialog */
        setDialog: function (core) {
            const lang = core.lang;
            const dialog = core.util.createElement('DIV');

            dialog.className = 'se-dialog-content';
            dialog.style.display = 'none';
            let html = '' +
                '<form class="editor_link">' +
                    '<div class="se-dialog-header">' +
                        '<button type="button" data-command="close" class="se-btn se-dialog-close" aria-label="Close" title="' + lang.dialogBox.close + '">' +
                            core.icons.cancel +
                        '</button>' +
                        '<span class="se-modal-title">' + lang.audio.title + '</span>' +
                    '</div>' +
                    '<div class="se-dialog-body">' +
                        '<div class="se-dialog-form">' +
                            '<label>' + lang.audio.file + '</label>' +
                            '<div class="se-dialog-form-files">' +
                                '<input class="se-input-form _se_audio_files" type="file" accept="audio/*" multiple="multiple" />' +
                                '<button type="button" data-command="filesRemove" class="se-btn se-dialog-files-edge-button" title="' + lang.controller.remove + '">' + core.icons.cancel + '</button>' +
                            '</div>' +
                        '</div>' +
                        '<div class="se-dialog-form">' +
                            '<label>' + lang.audio.url + '</label>' +
                            '<input class="se-input-form se-input-url" type="text" />' +
                        '</div>' +
                    '</div>' +
                    '<div class="se-dialog-footer">' +
                        '<button type="submit" class="se-btn-primary" title="' + lang.dialogBox.submitButton + '"><span>' + lang.dialogBox.submitButton + '</span></button>' +
                    '</div>' +
                '</form>';

            dialog.innerHTML = html;

            return dialog;
        },

        /** HTML - controller */
        setController: function (core) {
            const lang = core.lang;
            const icons = core.icons;
            const link_btn = core.util.createElement('DIV');

            link_btn.className = 'se-controller se-controller-link';
            link_btn.innerHTML = '' +
                '<div class="se-arrow se-arrow-up"></div>' +
                '<div class="link-content">' +
                    '<div class="se-btn-group">' +
                        '<button type="button" data-command="update" tabindex="-1" class="se-tooltip">' +
                            icons.edit +
                            '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.edit + '</span></span>' +
                        '</button>' +
                        '<button type="button" data-command="delete" tabindex="-1" class="se-tooltip">' +
                            icons.delete +
                            '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.remove + '</span></span>' +
                        '</button>' +
                    '</div>' +
                '</div>';

            return link_btn;
        },

        // Disable url input when uploading files
        _removeSelectedFiles: function (urlInput) {
            this.value = '';
            if (urlInput) urlInput.removeAttribute('disabled');
        },

        /**
         * @Required @Override fileManager
         */
        fileTags: ['audio'],

        /**
         * @Override core, fileManager, resizing
         * @description It is called from core.selectComponent.
         * @param {Element} element Target element
         */
        select: function (element) {
            this.plugins.customAudio.onModifyMode.call(this, element);
        },

        /**
         * @Override fileManager, resizing 
         * @param {Element} element Target element
         */
        destroy: function (element) {
            element = element || this.context.customAudio._element;
            const container = this.util.getParentElement(element, this.util.isComponent) || element;
            const dataIndex = element.getAttribute('data-index') * 1;
            const focusEl = (container.previousElementSibling || container.nextElementSibling);

            const emptyDiv = container.parentNode;
            this.util.removeItem(container);
            this.plugins.customAudio.init.call(this);
            this.controllersOff();

            if (emptyDiv !== this.context.element.wysiwyg) this.util.removeItemAllParents(emptyDiv, function (current) { return current.childNodes.length === 0; }, null);

            // focus
            this.focusEdge(focusEl);

            // fileManager event
            // (pluginName, data-index, "uploadEventHandler")
            this.plugins.fileManager.deleteInfo.call(this, 'customAudio', dataIndex, userFunc_audioUpload);

            // history stack
            this.history.push(false);
        },

        /**
         * @Override fileManager
         */
        checkFileInfo: function () {
            // (pluginName, [tag], "uploadEventHandler", "formatFixFunction", "using resizing module?")
            this.plugins.fileManager.checkInfo.call(this, 'customAudio', ['audio'], userFunc_audioUpload, this.plugins.customAudio.updateCover.bind(this), false);
        },

        /**
         * @Override fileManager
         */
        resetFileInfo: function () {
            // (pluginName, data-index, "uploadEventHandler")
            this.plugins.fileManager.resetInfo.call(this, 'customAudio', userFunc_audioUpload);
        },

        /**
         * @Required @Override dialog
         * This method is called just before the dialog opens.
         * @param {Boolean} update If "update" argument is true, it is not a new call, but a call to modify an already created element.
         */
        on: function (update) {
            if (!update) {
                this.plugins.customAudio.init.call(this);
            } else if (this.context.customAudio._element) {
                // "update" and "this.context.dialog.updateModal" are always the same value.
                // This code is an exception to the "link" plugin.
                this.context.dialog.updateModal = true;
                this.context.customAudio.urlInput.value = this.context.customAudio._element.src;
            }
        },

        /**
         * @Required @Override dialog
         * This method is called when the plugin button is clicked.
         * Open the modal window here.
         */
        open: function () {
            // open.call(core, pluginName, isModify)
            this.plugins.dialog.open.call(this, 'customAudio', 'customAudio' === this.currentControllerName);
        },

        submit: function (e) {
            const context = this.context.customAudio;

            e.preventDefault();
            e.stopPropagation();

            try {
                if (context.fileInput.files.length > 0) {
                    // upload files
                    this.plugins.customAudio.submitAction.call(this, context.fileInput.files);
                } else if (context.urlInput.value.trim().length > 0) {
                    // url
                    this.plugins.customAudio.setupUrl.call(this, context.urlInput);
                }
            } catch (error) {
                throw Error('[SUNEDITOR.audio.submit.fail] cause : "' + error.message + '"');
            } finally {
                this.plugins.dialog.close.call(this);
            }

            return false;
        },

        submitAction: function (fileList) {
            if (fileList.length === 0) return;

            let fileSize = 0;
            const files = [];
            for (let i = 0, len = fileList.length; i < len; i++) {
                if (/audio/i.test(fileList[i].type)) {
                    files.push(fileList[i]);
                    fileSize += fileList[i].size;
                }
            }

            const context = this.context.customAudio;
            const audioPlugin = this.plugins.customAudio;

            context._uploadFileLength = files.length;
            const filesLen = this.context.dialog.updateModal ? 1 : files.length;
            const info = {
                isUpdate: this.context.dialog.updateModal,
                element: context._element
            };

            // create formData
            const formData = new FormData();
            for (let i = 0; i < filesLen; i++) {
                formData.append('file-' + i, files[i]);
            }

            // fileManager - upload
            // (uploadURL, uploadHeader, formData, callBack, errorCallBack)
            this.plugins.fileManager.upload.call(this, 'http://localhost:3000', {}, formData, audioPlugin.callBack_upload.bind(this, info), audioPlugin.callBack_error);
        },

        callBack_upload: function (info, xmlHttp) {
            const response = JSON.parse(xmlHttp.responseText);

            if (response.errorMessage) {
                this.functions.noticeOpen(response.errorMessage);
            } else {
                const fileList = response.result;
                let oAudio = null;
                if (info.isUpdate) {
                    oAudio = info.element;
                } else {
                    oAudio = this.util.createElement('AUDIO');
                    oAudio.setAttribute('controls', true);
                }

                for (let i = 0, len = fileList.length, file; i < len; i++) {
                    file = { name: fileList[i].name, size: fileList[i].size };
                    this.plugins.customAudio.create_audio.call(this, oAudio, fileList[i].url, file, info.isUpdate);
                }
            }
        },

        callBack_error: function (errorMessage, response, core) {
            core.functions.noticeOpen(errorMessage | response.toString());
        },

        setupUrl: function () {
            try {
                this.showLoading();
                const context = this.context.customAudio;
                const src = context.urlInput.value.trim();

                if (src.length === 0) return false;

                const oAudio = this.util.createElement('AUDIO');
                oAudio.setAttribute('controls', true);

                // When opened for modification "this.context.dialog.updateModal" is true
                this.plugins.customAudio.create_audio.call(this, oAudio, src, null, this.context.dialog.updateModal);
            } catch (error) {
                throw Error('[SUNEDITOR.audio.audio.fail] cause : "' + error.message + '"');
            } finally {
                this.closeLoading();
            }
        },

        // create or update
        create_audio: function (element, src, file, isUpdate) {
            const context = this.context.customAudio;
            
            // create new tag
            if (!isUpdate) {
                element.src = src;

                // In order to use it in the form of components such as images and videos, 
                // you need to create component tags by calling the "set_cover" and "set_container" functions of the "component" module.
                const cover = this.plugins.component.set_cover.call(this, element);
                const container = this.plugins.component.set_container.call(this, cover, '');
                this.insertComponent(container, false);
            } // update
            else {
                if (context._element) element = context._element;
                if (element && element.src !== src) {
                    element.src = src
                } else {
                    return;
                }
            }

            // call fileManager.setInfo when updated tag
            // (pluginName, element, "uploadEventHandler", file, "using resizing module")
            this.plugins.fileManager.setInfo.call(this, 'customAudio', element, userFunc_audioUpload, file, false);
            this.history.push(false);
        },

        // Update container for "audio" tag not matching format to be used in "checkFileInfo"
        updateCover: function (element) {
            const context = this.context.customAudio;
            element.setAttribute('controls', true);
            
            // find component element
            const existElement = this.util.getParentElement(element, this.util.isMediaComponent) || 
                this.util.getParentElement(element, function (current) {
                    return this.isWysiwygDiv(current.parentNode);
                }.bind(this.util));

            // clone element
            context._element = element = element.cloneNode(false);
            const cover = this.plugins.component.set_cover.call(this, element);
            const container = this.plugins.component.set_container.call(this, cover, 'se-video-container');

            existElement.parentNode.replaceChild(container, existElement);

            // call fileManager.setInfo when updated tag
            // (pluginName, element, "uploadEventHandler", file, "using resizing module")
            this.plugins.fileManager.setInfo.call(this, 'customAudio', element, userFunc_audioUpload, null, false);
        },

        /**
         * @Required @Override fileManager, resizing
         * @param {Element} selectionTag Selected element
         * @param {Object} size Size object{w, h, t, 1} of "core.plugins.resizing.call_controller_resize" return value when if using "resizing" module
         */
        onModifyMode: function (selectionTag) {
            const context = this.context.customAudio;

            const controller = context.controller;
            const offset = this.util.getOffset(selectionTag, this.context.element.wysiwygFrame);
            controller.style.top = (offset.top + selectionTag.offsetHeight + 10) + 'px';
            controller.style.left = (offset.left - this.context.element.wysiwygFrame.scrollLeft) + 'px';

            controller.style.display = 'block';

            const overLeft = this.context.element.wysiwygFrame.offsetWidth - (controller.offsetLeft + controller.offsetWidth);
            if (overLeft < 0) {
                controller.style.left = (controller.offsetLeft + overLeft) + 'px';
                controller.firstElementChild.style.left = (20 - overLeft) + 'px';
            } else {
                controller.firstElementChild.style.left = '20px';
            }
            
            // Show controller at editor area (controller elements, function, "controller target element(@Required)", "controller name(@Required)", etc..)
            this.controllersOn(controller, selectionTag, this.plugins.customAudio.init.bind(this), 'customAudio');

            // set modify mode context
            selectionTag.style.border = '1px solid #80bdff';
            context._element = selectionTag;
            context._cover = this.util.getParentElement(selectionTag, 'FIGURE');
            context._container = this.util.getParentElement(selectionTag, this.util.isComponent);
        },

        /**
         * @Required @Override fileManager, resizing
         */
        openModify: function (notOpen) {
            this.context.customAudio.urlInput.value = this.context.customAudio._element.src;
            if (!notOpen) this.plugins.dialog.open.call(this, 'customAudio', true);
        },

        onClick_controller: function (e) {
            e.stopPropagation();

            const command = e.target.getAttribute('data-command');
            if (!command) return;

            e.preventDefault();

            if (/update/.test(command)) {
                this.plugins.customAudio.openModify.call(this, false);
            }
            else { /** delete */
                this.plugins.customAudio.destroy.call(this, this.context.customAudio._element);
            }

            this.controllersOff();
        },

        /**
         * @Required @Override dialog
         * This method is called when the dialog window is closed.
         * Initialize the properties.
         */
        init: function () {
            if (this.context.dialog.updateModal) return;

            const context = this.context.customAudio;
            if (context._element) context._element.style.border = '';
            context.controller.style.display = 'none';
            context._element = null;
            context.fileInput.value = '';
            context.urlInput.value = '';
        }
    };

    SUNEDITOR.create(document.getElementById('ex_container'), {
        plugins: [custom_container],
        buttonList: [
            [
                {
                    name: 'custom_container', 
                    dataDisplay:'container',
                    title:'custom_container', 
                    buttonClass:'', 
                    innerHTML:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="width:24px;height:24px;"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>'
                }
            ]
        ]
    });

    SUNEDITOR.create(document.getElementById('ex_command'), {
        plugins: [plugin_command, plugin_command_2],
        buttonList: [
            ['customCommand', 'customCommand_2']
        ]
    });

    SUNEDITOR.create(document.getElementById('ex_submenu'), {
        plugins: [plugin_submenu],
        buttonList: [
            ['custom_plugin_submenu']
        ]
    });

    SUNEDITOR.create(document.getElementById('ex_dialog'), {
        plugins: [plugin_dialog],
        buttonList: [
            [
                {
                    name: 'customLink', 
                    dataDisplay:'dialog',
                    title:'Custom link', 
                    buttonClass:'', 
                    innerHTML:'<svg viewBox="0 0 24 24"><path d="M10.59,13.41C11,13.8 11,14.44 10.59,14.83C10.2,15.22 9.56,15.22 9.17,14.83C7.22,12.88 7.22,9.71 9.17,7.76V7.76L12.71,4.22C14.66,2.27 17.83,2.27 19.78,4.22C21.73,6.17 21.73,9.34 19.78,11.29L18.29,12.78C18.3,11.96 18.17,11.14 17.89,10.36L18.36,9.88C19.54,8.71 19.54,6.81 18.36,5.64C17.19,4.46 15.29,4.46 14.12,5.64L10.59,9.17C9.41,10.34 9.41,12.24 10.59,13.41M13.41,9.17C13.8,8.78 14.44,8.78 14.83,9.17C16.78,11.12 16.78,14.29 14.83,16.24V16.24L11.29,19.78C9.34,21.73 6.17,21.73 4.22,19.78C2.27,17.83 2.27,14.66 4.22,12.71L5.71,11.22C5.7,12.04 5.83,12.86 6.11,13.65L5.64,14.12C4.46,15.29 4.46,17.19 5.64,18.36C6.81,19.54 8.71,19.54 9.88,18.36L13.41,14.83C14.59,13.66 14.59,11.76 13.41,10.59C13,10.2 13,9.56 13.41,9.17Z" /></svg>'
                }
            ]
        ]
    });

    SUNEDITOR.create(document.getElementById('ex_dialog_component_fileManager'), {
        plugins: [plugin_dialog_component_fileManager],
        buttonList: [
            ['customAudio', 'preview']
        ]
    });
</script>
</body>
</html>
